github.com/bloxroute-labs/bor@v0.1.4/crypto/bn256/cloudflare/gfp_generic.go (about)

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