gfp_generic.go 3.2 KB

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