You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
4.3 KiB

  1. package r1csqapFloat
  2. import "math/big"
  3. func Transpose(matrix [][]*big.Float) [][]*big.Float {
  4. var r [][]*big.Float
  5. for i := 0; i < len(matrix[0]); i++ {
  6. var row []*big.Float
  7. for j := 0; j < len(matrix); j++ {
  8. row = append(row, matrix[j][i])
  9. }
  10. r = append(r, row)
  11. }
  12. return r
  13. }
  14. func ArrayOfBigZeros(num int) []*big.Float {
  15. bigZero := big.NewFloat(float64(0))
  16. var r []*big.Float
  17. for i := 0; i < num; i++ {
  18. r = append(r, bigZero)
  19. }
  20. return r
  21. }
  22. func PolMul(a, b []*big.Float) []*big.Float {
  23. r := ArrayOfBigZeros(len(a) + len(b) - 1)
  24. for i := 0; i < len(a); i++ {
  25. for j := 0; j < len(b); j++ {
  26. r[i+j] = new(big.Float).Add(
  27. r[i+j],
  28. new(big.Float).Mul(a[i], b[j]))
  29. }
  30. }
  31. return r
  32. }
  33. func PolDiv(a, b []*big.Float) ([]*big.Float, []*big.Float) {
  34. // https://en.wikipedia.org/wiki/Division_algorithm
  35. r := ArrayOfBigZeros(len(a) - len(b) + 1)
  36. rem := a
  37. for len(rem) >= len(b) {
  38. l := new(big.Float).Quo(rem[len(rem)-1], b[len(b)-1])
  39. pos := len(rem) - len(b)
  40. r[pos] = l
  41. aux := ArrayOfBigZeros(pos)
  42. aux1 := append(aux, l)
  43. aux2 := PolSub(rem, PolMul(b, aux1))
  44. rem = aux2[:len(aux2)-1]
  45. }
  46. return r, rem
  47. }
  48. func max(a, b int) int {
  49. if a > b {
  50. return a
  51. }
  52. return b
  53. }
  54. func PolAdd(a, b []*big.Float) []*big.Float {
  55. r := ArrayOfBigZeros(max(len(a), len(b)))
  56. for i := 0; i < len(a); i++ {
  57. r[i] = new(big.Float).Add(r[i], a[i])
  58. }
  59. for i := 0; i < len(b); i++ {
  60. r[i] = new(big.Float).Add(r[i], b[i])
  61. }
  62. return r
  63. }
  64. func PolSub(a, b []*big.Float) []*big.Float {
  65. r := ArrayOfBigZeros(max(len(a), len(b)))
  66. for i := 0; i < len(a); i++ {
  67. r[i] = new(big.Float).Add(r[i], a[i])
  68. }
  69. for i := 0; i < len(b); i++ {
  70. bneg := new(big.Float).Mul(b[i], big.NewFloat(float64(-1)))
  71. r[i] = new(big.Float).Add(r[i], bneg)
  72. }
  73. return r
  74. }
  75. func FloatPow(a *big.Float, e int) *big.Float {
  76. if e == 0 {
  77. return big.NewFloat(float64(1))
  78. }
  79. result := new(big.Float).Copy(a)
  80. for i := 0; i < e-1; i++ {
  81. result = new(big.Float).Mul(result, a)
  82. }
  83. return result
  84. }
  85. func PolEval(v []*big.Float, x *big.Float) *big.Float {
  86. r := big.NewFloat(float64(0))
  87. for i := 0; i < len(v); i++ {
  88. xi := FloatPow(x, i)
  89. elem := new(big.Float).Mul(v[i], xi)
  90. r = new(big.Float).Add(r, elem)
  91. }
  92. return r
  93. }
  94. func NewPolZeroAt(pointPos, totalPoints int, height *big.Float) []*big.Float {
  95. fac := 1
  96. for i := 1; i < totalPoints+1; i++ {
  97. if i != pointPos {
  98. fac = fac * (pointPos - i)
  99. }
  100. }
  101. facBig := big.NewFloat(float64(fac))
  102. hf := new(big.Float).Quo(height, facBig)
  103. r := []*big.Float{hf}
  104. for i := 1; i < totalPoints+1; i++ {
  105. if i != pointPos {
  106. ineg := big.NewFloat(float64(-i))
  107. b1 := big.NewFloat(float64(1))
  108. r = PolMul(r, []*big.Float{ineg, b1})
  109. }
  110. }
  111. return r
  112. }
  113. func LagrangeInterpolation(v []*big.Float) []*big.Float {
  114. // https://en.wikipedia.org/wiki/Lagrange_polynomial
  115. var r []*big.Float
  116. for i := 0; i < len(v); i++ {
  117. r = PolAdd(r, NewPolZeroAt(i+1, len(v), v[i]))
  118. }
  119. //
  120. return r
  121. }
  122. func R1CSToQAP(a, b, c [][]*big.Float) ([][]*big.Float, [][]*big.Float, [][]*big.Float, []*big.Float) {
  123. aT := Transpose(a)
  124. bT := Transpose(b)
  125. cT := Transpose(c)
  126. var alphas [][]*big.Float
  127. for i := 0; i < len(aT); i++ {
  128. alphas = append(alphas, LagrangeInterpolation(aT[i]))
  129. }
  130. var betas [][]*big.Float
  131. for i := 0; i < len(bT); i++ {
  132. betas = append(betas, LagrangeInterpolation(bT[i]))
  133. }
  134. var gammas [][]*big.Float
  135. for i := 0; i < len(cT); i++ {
  136. gammas = append(gammas, LagrangeInterpolation(cT[i]))
  137. }
  138. z := []*big.Float{big.NewFloat(float64(1))}
  139. for i := 1; i < len(aT[0])+1; i++ {
  140. ineg := big.NewFloat(float64(-i))
  141. b1 := big.NewFloat(float64(1))
  142. z = PolMul(z, []*big.Float{ineg, b1})
  143. }
  144. return alphas, betas, gammas, z
  145. }
  146. func CombinePolynomials(r []*big.Float, ap, bp, cp [][]*big.Float) ([]*big.Float, []*big.Float, []*big.Float, []*big.Float) {
  147. var alpha []*big.Float
  148. for i := 0; i < len(r); i++ {
  149. m := PolMul([]*big.Float{r[i]}, ap[i])
  150. alpha = PolAdd(alpha, m)
  151. }
  152. var beta []*big.Float
  153. for i := 0; i < len(r); i++ {
  154. m := PolMul([]*big.Float{r[i]}, bp[i])
  155. beta = PolAdd(beta, m)
  156. }
  157. var gamma []*big.Float
  158. for i := 0; i < len(r); i++ {
  159. m := PolMul([]*big.Float{r[i]}, cp[i])
  160. gamma = PolAdd(gamma, m)
  161. }
  162. px := PolSub(PolMul(alpha, beta), gamma)
  163. return alpha, beta, gamma, px
  164. }
  165. func DivisorPolinomial(px, z []*big.Float) []*big.Float {
  166. quo, _ := PolDiv(px, z)
  167. return quo
  168. }