github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/crypto/bn256/cloudflare/gfp_generic.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //+建设!AMD64!ARM64通用
    10  
    11  package bn256
    12  
    13  func gfpCarry(a *gfP, head uint64) {
    14  	b := &gfP{}
    15  
    16  	var carry uint64
    17  	for i, pi := range p2 {
    18  		ai := a[i]
    19  		bi := ai - pi - carry
    20  		b[i] = bi
    21  		carry = (pi&^ai | (pi|^ai)&bi) >> 63
    22  	}
    23  	carry = carry &^ head
    24  
    25  //如果b为负,则返回a。
    26  //否则返回B。
    27  	carry = -carry
    28  	ncarry := ^carry
    29  	for i := 0; i < 4; i++ {
    30  		a[i] = (a[i] & carry) | (b[i] & ncarry)
    31  	}
    32  }
    33  
    34  func gfpNeg(c, a *gfP) {
    35  	var carry uint64
    36  	for i, pi := range p2 {
    37  		ai := a[i]
    38  		ci := pi - ai - carry
    39  		c[i] = ci
    40  		carry = (ai&^pi | (ai|^pi)&ci) >> 63
    41  	}
    42  	gfpCarry(c, 0)
    43  }
    44  
    45  func gfpAdd(c, a, b *gfP) {
    46  	var carry uint64
    47  	for i, ai := range a {
    48  		bi := b[i]
    49  		ci := ai + bi + carry
    50  		c[i] = ci
    51  		carry = (ai&bi | (ai|bi)&^ci) >> 63
    52  	}
    53  	gfpCarry(c, carry)
    54  }
    55  
    56  func gfpSub(c, a, b *gfP) {
    57  	t := &gfP{}
    58  
    59  	var carry uint64
    60  	for i, pi := range p2 {
    61  		bi := b[i]
    62  		ti := pi - bi - carry
    63  		t[i] = ti
    64  		carry = (bi&^pi | (bi|^pi)&ti) >> 63
    65  	}
    66  
    67  	carry = 0
    68  	for i, ai := range a {
    69  		ti := t[i]
    70  		ci := ai + ti + carry
    71  		c[i] = ci
    72  		carry = (ai&ti | (ai|ti)&^ci) >> 63
    73  	}
    74  	gfpCarry(c, carry)
    75  }
    76  
    77  func mul(a, b [4]uint64) [8]uint64 {
    78  	const (
    79  		mask16 uint64 = 0x0000ffff
    80  		mask32 uint64 = 0xffffffff
    81  	)
    82  
    83  	var buff [32]uint64
    84  	for i, ai := range a {
    85  		a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48
    86  
    87  		for j, bj := range b {
    88  			b0, b2 := bj&mask32, bj>>32
    89  
    90  			off := 4 * (i + j)
    91  			buff[off+0] += a0 * b0
    92  			buff[off+1] += a1 * b0
    93  			buff[off+2] += a2*b0 + a0*b2
    94  			buff[off+3] += a3*b0 + a1*b2
    95  			buff[off+4] += a2 * b2
    96  			buff[off+5] += a3 * b2
    97  		}
    98  	}
    99  
   100  	for i := uint(1); i < 4; i++ {
   101  		shift := 16 * i
   102  
   103  		var head, carry uint64
   104  		for j := uint(0); j < 8; j++ {
   105  			block := 4 * j
   106  
   107  			xi := buff[block]
   108  			yi := (buff[block+i] << shift) + head
   109  			zi := xi + yi + carry
   110  			buff[block] = zi
   111  			carry = (xi&yi | (xi|yi)&^zi) >> 63
   112  
   113  			head = buff[block+i] >> (64 - shift)
   114  		}
   115  	}
   116  
   117  	return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]}
   118  }
   119  
   120  func halfMul(a, b [4]uint64) [4]uint64 {
   121  	const (
   122  		mask16 uint64 = 0x0000ffff
   123  		mask32 uint64 = 0xffffffff
   124  	)
   125  
   126  	var buff [18]uint64
   127  	for i, ai := range a {
   128  		a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48
   129  
   130  		for j, bj := range b {
   131  			if i+j > 3 {
   132  				break
   133  			}
   134  			b0, b2 := bj&mask32, bj>>32
   135  
   136  			off := 4 * (i + j)
   137  			buff[off+0] += a0 * b0
   138  			buff[off+1] += a1 * b0
   139  			buff[off+2] += a2*b0 + a0*b2
   140  			buff[off+3] += a3*b0 + a1*b2
   141  			buff[off+4] += a2 * b2
   142  			buff[off+5] += a3 * b2
   143  		}
   144  	}
   145  
   146  	for i := uint(1); i < 4; i++ {
   147  		shift := 16 * i
   148  
   149  		var head, carry uint64
   150  		for j := uint(0); j < 4; j++ {
   151  			block := 4 * j
   152  
   153  			xi := buff[block]
   154  			yi := (buff[block+i] << shift) + head
   155  			zi := xi + yi + carry
   156  			buff[block] = zi
   157  			carry = (xi&yi | (xi|yi)&^zi) >> 63
   158  
   159  			head = buff[block+i] >> (64 - shift)
   160  		}
   161  	}
   162  
   163  	return [4]uint64{buff[0], buff[4], buff[8], buff[12]}
   164  }
   165  
   166  func gfpMul(c, a, b *gfP) {
   167  	T := mul(*a, *b)
   168  	m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np)
   169  	t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2)
   170  
   171  	var carry uint64
   172  	for i, Ti := range T {
   173  		ti := t[i]
   174  		zi := Ti + ti + carry
   175  		T[i] = zi
   176  		carry = (Ti&ti | (Ti|ti)&^zi) >> 63
   177  	}
   178  
   179  	*c = gfP{T[4], T[5], T[6], T[7]}
   180  	gfpCarry(c, carry)
   181  }