github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-756/fr/polynomial/polynomial.go (about)

     1  // Copyright 2020 Consensys Software Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Code generated by consensys/gnark-crypto DO NOT EDIT
    16  
    17  package polynomial
    18  
    19  import (
    20  	"github.com/consensys/gnark-crypto/ecc/bw6-756/fr"
    21  	"github.com/consensys/gnark-crypto/utils"
    22  	"strconv"
    23  	"strings"
    24  )
    25  
    26  // Polynomial represented by coefficients in the field.
    27  type Polynomial []fr.Element
    28  
    29  // Degree returns the degree of the polynomial, which is the length of Data.
    30  func (p *Polynomial) Degree() uint64 {
    31  	return uint64(len(*p) - 1)
    32  }
    33  
    34  // Eval evaluates p at v
    35  // returns a fr.Element
    36  func (p *Polynomial) Eval(v *fr.Element) fr.Element {
    37  
    38  	res := (*p)[len(*p)-1]
    39  	for i := len(*p) - 2; i >= 0; i-- {
    40  		res.Mul(&res, v)
    41  		res.Add(&res, &(*p)[i])
    42  	}
    43  
    44  	return res
    45  }
    46  
    47  // Clone returns a copy of the polynomial
    48  func (p *Polynomial) Clone() Polynomial {
    49  	_p := make(Polynomial, len(*p))
    50  	copy(_p, *p)
    51  	return _p
    52  }
    53  
    54  // Set to another polynomial
    55  func (p *Polynomial) Set(p1 Polynomial) {
    56  	if len(*p) != len(p1) {
    57  		*p = p1.Clone()
    58  		return
    59  	}
    60  
    61  	for i := 0; i < len(p1); i++ {
    62  		(*p)[i].Set(&p1[i])
    63  	}
    64  }
    65  
    66  // AddConstantInPlace adds a constant to the polynomial, modifying p
    67  func (p *Polynomial) AddConstantInPlace(c *fr.Element) {
    68  	for i := 0; i < len(*p); i++ {
    69  		(*p)[i].Add(&(*p)[i], c)
    70  	}
    71  }
    72  
    73  // SubConstantInPlace subs a constant to the polynomial, modifying p
    74  func (p *Polynomial) SubConstantInPlace(c *fr.Element) {
    75  	for i := 0; i < len(*p); i++ {
    76  		(*p)[i].Sub(&(*p)[i], c)
    77  	}
    78  }
    79  
    80  // ScaleInPlace multiplies p by v, modifying p
    81  func (p *Polynomial) ScaleInPlace(c *fr.Element) {
    82  	for i := 0; i < len(*p); i++ {
    83  		(*p)[i].Mul(&(*p)[i], c)
    84  	}
    85  }
    86  
    87  // Scale multiplies p0 by v, storing the result in p
    88  func (p *Polynomial) Scale(c *fr.Element, p0 Polynomial) {
    89  	if len(*p) != len(p0) {
    90  		*p = make(Polynomial, len(p0))
    91  	}
    92  	for i := 0; i < len(p0); i++ {
    93  		(*p)[i].Mul(c, &p0[i])
    94  	}
    95  }
    96  
    97  // Add adds p1 to p2
    98  // This function allocates a new slice unless p == p1 or p == p2
    99  func (p *Polynomial) Add(p1, p2 Polynomial) *Polynomial {
   100  
   101  	bigger := p1
   102  	smaller := p2
   103  	if len(bigger) < len(smaller) {
   104  		bigger, smaller = smaller, bigger
   105  	}
   106  
   107  	if len(*p) == len(bigger) && (&(*p)[0] == &bigger[0]) {
   108  		for i := 0; i < len(smaller); i++ {
   109  			(*p)[i].Add(&(*p)[i], &smaller[i])
   110  		}
   111  		return p
   112  	}
   113  
   114  	if len(*p) == len(smaller) && (&(*p)[0] == &smaller[0]) {
   115  		for i := 0; i < len(smaller); i++ {
   116  			(*p)[i].Add(&(*p)[i], &bigger[i])
   117  		}
   118  		*p = append(*p, bigger[len(smaller):]...)
   119  		return p
   120  	}
   121  
   122  	res := make(Polynomial, len(bigger))
   123  	copy(res, bigger)
   124  	for i := 0; i < len(smaller); i++ {
   125  		res[i].Add(&res[i], &smaller[i])
   126  	}
   127  	*p = res
   128  	return p
   129  }
   130  
   131  // Sub subtracts p2 from p1
   132  // TODO make interface more consistent with Add
   133  func (p *Polynomial) Sub(p1, p2 Polynomial) *Polynomial {
   134  	if len(p1) != len(p2) || len(p2) != len(*p) {
   135  		return nil
   136  	}
   137  	for i := 0; i < len(*p); i++ {
   138  		(*p)[i].Sub(&p1[i], &p2[i])
   139  	}
   140  	return p
   141  }
   142  
   143  // Equal checks equality between two polynomials
   144  func (p *Polynomial) Equal(p1 Polynomial) bool {
   145  	if (*p == nil) != (p1 == nil) {
   146  		return false
   147  	}
   148  
   149  	if len(*p) != len(p1) {
   150  		return false
   151  	}
   152  
   153  	for i := range p1 {
   154  		if !(*p)[i].Equal(&p1[i]) {
   155  			return false
   156  		}
   157  	}
   158  
   159  	return true
   160  }
   161  
   162  func (p Polynomial) SetZero() {
   163  	for i := 0; i < len(p); i++ {
   164  		p[i].SetZero()
   165  	}
   166  }
   167  
   168  func (p Polynomial) Text(base int) string {
   169  
   170  	var builder strings.Builder
   171  
   172  	first := true
   173  	for d := len(p) - 1; d >= 0; d-- {
   174  		if p[d].IsZero() {
   175  			continue
   176  		}
   177  
   178  		pD := p[d]
   179  		pDText := pD.Text(base)
   180  
   181  		initialLen := builder.Len()
   182  
   183  		if pDText[0] == '-' {
   184  			pDText = pDText[1:]
   185  			if first {
   186  				builder.WriteString("-")
   187  			} else {
   188  				builder.WriteString(" - ")
   189  			}
   190  		} else if !first {
   191  			builder.WriteString(" + ")
   192  		}
   193  
   194  		first = false
   195  
   196  		if !pD.IsOne() || d == 0 {
   197  			builder.WriteString(pDText)
   198  		}
   199  
   200  		if builder.Len()-initialLen > 10 {
   201  			builder.WriteString("×")
   202  		}
   203  
   204  		if d != 0 {
   205  			builder.WriteString("X")
   206  		}
   207  		if d > 1 {
   208  			builder.WriteString(
   209  				utils.ToSuperscript(strconv.Itoa(d)),
   210  			)
   211  		}
   212  
   213  	}
   214  
   215  	if first {
   216  		return "0"
   217  	}
   218  
   219  	return builder.String()
   220  }