github.com/consensys/gnark-crypto@v0.14.0/internal/generator/polynomial/template/polynomial.go.tmpl (about) 1 import ( 2 "{{.FieldPackagePath}}" 3 "github.com/consensys/gnark-crypto/utils" 4 "strconv" 5 "strings" 6 ) 7 8 // Polynomial represented by coefficients in the field. 9 type Polynomial []{{.ElementType}} 10 11 // Degree returns the degree of the polynomial, which is the length of Data. 12 func (p *Polynomial) Degree() uint64 { 13 return uint64(len(*p) - 1) 14 } 15 16 // Eval evaluates p at v 17 // returns a {{.ElementType}} 18 func (p *Polynomial) Eval(v *{{.ElementType}}) {{.ElementType}} { 19 20 res := (*p)[len(*p) - 1] 21 for i := len(*p) - 2; i >= 0; i-- { 22 res.Mul(&res, v) 23 res.Add(&res, &(*p)[i]) 24 } 25 26 return res 27 } 28 29 // Clone returns a copy of the polynomial 30 func (p *Polynomial) Clone() Polynomial { 31 _p := make(Polynomial, len(*p)) 32 copy(_p, *p) 33 return _p 34 } 35 36 // Set to another polynomial 37 func (p *Polynomial) Set(p1 Polynomial) { 38 if len(*p) != len(p1) { 39 *p = p1.Clone() 40 return 41 } 42 43 for i := 0; i < len(p1); i++ { 44 (*p)[i].Set(&p1[i]) 45 } 46 } 47 48 // AddConstantInPlace adds a constant to the polynomial, modifying p 49 func (p *Polynomial) AddConstantInPlace(c *{{.ElementType}}) { 50 for i := 0; i < len(*p); i++ { 51 (*p)[i].Add(&(*p)[i], c) 52 } 53 } 54 55 // SubConstantInPlace subs a constant to the polynomial, modifying p 56 func (p *Polynomial) SubConstantInPlace(c *{{.ElementType}}) { 57 for i := 0; i < len(*p); i++ { 58 (*p)[i].Sub(&(*p)[i], c) 59 } 60 } 61 62 // ScaleInPlace multiplies p by v, modifying p 63 func (p *Polynomial) ScaleInPlace(c *{{.ElementType}}) { 64 for i := 0; i < len(*p); i++ { 65 (*p)[i].Mul(&(*p)[i], c) 66 } 67 } 68 69 // Scale multiplies p0 by v, storing the result in p 70 func (p *Polynomial) Scale(c *{{.ElementType}}, p0 Polynomial) { 71 if len(*p) != len(p0) { 72 *p = make(Polynomial, len(p0)) 73 } 74 for i := 0; i < len(p0); i++ { 75 (*p)[i].Mul(c, &p0[i]) 76 } 77 } 78 79 // Add adds p1 to p2 80 // This function allocates a new slice unless p == p1 or p == p2 81 func (p *Polynomial) Add(p1, p2 Polynomial) *Polynomial { 82 83 bigger := p1 84 smaller := p2 85 if len(bigger) < len(smaller) { 86 bigger, smaller = smaller, bigger 87 } 88 89 if len(*p) == len(bigger) && (&(*p)[0] == &bigger[0]) { 90 for i:=0; i < len(smaller); i++ { 91 (*p)[i].Add(&(*p)[i], &smaller[i]) 92 } 93 return p 94 } 95 96 if len(*p) == len(smaller) && (&(*p)[0] == &smaller[0]) { 97 for i:=0; i < len(smaller); i++ { 98 (*p)[i].Add(&(*p)[i], &bigger[i]) 99 } 100 *p = append(*p, bigger[len(smaller):]...) 101 return p 102 } 103 104 res := make(Polynomial, len(bigger)) 105 copy(res, bigger) 106 for i:=0; i < len(smaller); i++ { 107 res[i].Add(&res[i], &smaller[i]) 108 } 109 *p = res 110 return p 111 } 112 113 // Sub subtracts p2 from p1 114 // TODO make interface more consistent with Add 115 func (p *Polynomial) Sub(p1, p2 Polynomial) *Polynomial { 116 if len(p1) != len(p2) || len(p2) != len(*p) { 117 return nil 118 } 119 for i := 0; i < len(*p); i++ { 120 (*p)[i].Sub(&p1[i], &p2[i]) 121 } 122 return p 123 } 124 125 // Equal checks equality between two polynomials 126 func (p *Polynomial) Equal(p1 Polynomial) bool { 127 if (*p == nil) != (p1 == nil) { 128 return false 129 } 130 131 if len(*p) != len(p1) { 132 return false 133 } 134 135 for i := range p1 { 136 if !(*p)[i].Equal(&p1[i]) { 137 return false 138 } 139 } 140 141 return true 142 } 143 144 func (p Polynomial) SetZero() { 145 for i := 0; i < len(p); i++ { 146 p[i].SetZero() 147 } 148 } 149 150 func (p Polynomial) Text(base int) string { 151 152 var builder strings.Builder 153 154 first := true 155 for d := len(p) - 1; d >= 0; d-- { 156 if p[d].IsZero() { 157 continue 158 } 159 160 pD := p[d] 161 pDText := pD.Text(base) 162 163 initialLen := builder.Len() 164 165 if pDText[0] == '-' { 166 pDText = pDText[1:] 167 if first { 168 builder.WriteString("-") 169 } else { 170 builder.WriteString(" - ") 171 } 172 } else if !first { 173 builder.WriteString(" + ") 174 } 175 176 first = false 177 178 if !pD.IsOne() || d == 0 { 179 builder.WriteString(pDText) 180 } 181 182 if builder.Len()-initialLen > 10 { 183 builder.WriteString("×") 184 } 185 186 if d != 0 { 187 builder.WriteString("X") 188 } 189 if d > 1 { 190 builder.WriteString( 191 utils.ToSuperscript(strconv.Itoa(d)), 192 ) 193 } 194 195 } 196 197 if first { 198 return "0" 199 } 200 201 return builder.String() 202 }