github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/crypto/bn256/cloudflare/gfp_generic.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:36</date>
    10  //</624342625251495936>
    11  
    12  //+建设!AMD64!ARM64通用
    13  
    14  package bn256
    15  
    16  func gfpCarry(a *gfP, head uint64) {
    17  	b := &gfP{}
    18  
    19  	var carry uint64
    20  	for i, pi := range p2 {
    21  		ai := a[i]
    22  		bi := ai - pi - carry
    23  		b[i] = bi
    24  		carry = (pi&^ai | (pi|^ai)&bi) >> 63
    25  	}
    26  	carry = carry &^ head
    27  
    28  //如果b为负,则返回a。
    29  //否则返回B。
    30  	carry = -carry
    31  	ncarry := ^carry
    32  	for i := 0; i < 4; i++ {
    33  		a[i] = (a[i] & carry) | (b[i] & ncarry)
    34  	}
    35  }
    36  
    37  func gfpNeg(c, a *gfP) {
    38  	var carry uint64
    39  	for i, pi := range p2 {
    40  		ai := a[i]
    41  		ci := pi - ai - carry
    42  		c[i] = ci
    43  		carry = (ai&^pi | (ai|^pi)&ci) >> 63
    44  	}
    45  	gfpCarry(c, 0)
    46  }
    47  
    48  func gfpAdd(c, a, b *gfP) {
    49  	var carry uint64
    50  	for i, ai := range a {
    51  		bi := b[i]
    52  		ci := ai + bi + carry
    53  		c[i] = ci
    54  		carry = (ai&bi | (ai|bi)&^ci) >> 63
    55  	}
    56  	gfpCarry(c, carry)
    57  }
    58  
    59  func gfpSub(c, a, b *gfP) {
    60  	t := &gfP{}
    61  
    62  	var carry uint64
    63  	for i, pi := range p2 {
    64  		bi := b[i]
    65  		ti := pi - bi - carry
    66  		t[i] = ti
    67  		carry = (bi&^pi | (bi|^pi)&ti) >> 63
    68  	}
    69  
    70  	carry = 0
    71  	for i, ai := range a {
    72  		ti := t[i]
    73  		ci := ai + ti + carry
    74  		c[i] = ci
    75  		carry = (ai&ti | (ai|ti)&^ci) >> 63
    76  	}
    77  	gfpCarry(c, carry)
    78  }
    79  
    80  func mul(a, b [4]uint64) [8]uint64 {
    81  	const (
    82  		mask16 uint64 = 0x0000ffff
    83  		mask32 uint64 = 0xffffffff
    84  	)
    85  
    86  	var buff [32]uint64
    87  	for i, ai := range a {
    88  		a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48
    89  
    90  		for j, bj := range b {
    91  			b0, b2 := bj&mask32, bj>>32
    92  
    93  			off := 4 * (i + j)
    94  			buff[off+0] += a0 * b0
    95  			buff[off+1] += a1 * b0
    96  			buff[off+2] += a2*b0 + a0*b2
    97  			buff[off+3] += a3*b0 + a1*b2
    98  			buff[off+4] += a2 * b2
    99  			buff[off+5] += a3 * b2
   100  		}
   101  	}
   102  
   103  	for i := uint(1); i < 4; i++ {
   104  		shift := 16 * i
   105  
   106  		var head, carry uint64
   107  		for j := uint(0); j < 8; j++ {
   108  			block := 4 * j
   109  
   110  			xi := buff[block]
   111  			yi := (buff[block+i] << shift) + head
   112  			zi := xi + yi + carry
   113  			buff[block] = zi
   114  			carry = (xi&yi | (xi|yi)&^zi) >> 63
   115  
   116  			head = buff[block+i] >> (64 - shift)
   117  		}
   118  	}
   119  
   120  	return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]}
   121  }
   122  
   123  func halfMul(a, b [4]uint64) [4]uint64 {
   124  	const (
   125  		mask16 uint64 = 0x0000ffff
   126  		mask32 uint64 = 0xffffffff
   127  	)
   128  
   129  	var buff [18]uint64
   130  	for i, ai := range a {
   131  		a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48
   132  
   133  		for j, bj := range b {
   134  			if i+j > 3 {
   135  				break
   136  			}
   137  			b0, b2 := bj&mask32, bj>>32
   138  
   139  			off := 4 * (i + j)
   140  			buff[off+0] += a0 * b0
   141  			buff[off+1] += a1 * b0
   142  			buff[off+2] += a2*b0 + a0*b2
   143  			buff[off+3] += a3*b0 + a1*b2
   144  			buff[off+4] += a2 * b2
   145  			buff[off+5] += a3 * b2
   146  		}
   147  	}
   148  
   149  	for i := uint(1); i < 4; i++ {
   150  		shift := 16 * i
   151  
   152  		var head, carry uint64
   153  		for j := uint(0); j < 4; j++ {
   154  			block := 4 * j
   155  
   156  			xi := buff[block]
   157  			yi := (buff[block+i] << shift) + head
   158  			zi := xi + yi + carry
   159  			buff[block] = zi
   160  			carry = (xi&yi | (xi|yi)&^zi) >> 63
   161  
   162  			head = buff[block+i] >> (64 - shift)
   163  		}
   164  	}
   165  
   166  	return [4]uint64{buff[0], buff[4], buff[8], buff[12]}
   167  }
   168  
   169  func gfpMul(c, a, b *gfP) {
   170  	T := mul(*a, *b)
   171  	m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np)
   172  	t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2)
   173  
   174  	var carry uint64
   175  	for i, Ti := range T {
   176  		ti := t[i]
   177  		zi := Ti + ti + carry
   178  		T[i] = zi
   179  		carry = (Ti&ti | (Ti|ti)&^zi) >> 63
   180  	}
   181  
   182  	*c = gfP{T[4], T[5], T[6], T[7]}
   183  	gfpCarry(c, carry)
   184  }
   185