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  }