github.com/consensys/gnark-crypto@v0.14.0/field/generator/internal/templates/element/conv.go (about)

     1  package element
     2  
     3  const Conv = `
     4  
     5  // rSquare where r is the Montgommery constant
     6  // see section 2.3.2 of Tolga Acar's thesis
     7  // https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf
     8  var rSquare = {{.ElementName}}{
     9  	{{- range $i := .RSquare}}
    10  	{{$i}},{{end}}
    11  }
    12  
    13  // toMont converts z to Montgomery form
    14  // sets and returns z = z * r²
    15  func (z *{{.ElementName}}) toMont() *{{.ElementName}} {
    16  	return z.Mul(z, &rSquare)
    17  }
    18  
    19  // String returns the decimal representation of z as generated by
    20  // z.Text(10).
    21  func (z *{{.ElementName}}) String() string {
    22  	return z.Text(10)
    23  }
    24  
    25  // toBigInt returns z as a big.Int in Montgomery form
    26  func (z *{{.ElementName}}) toBigInt(res *big.Int) *big.Int {
    27         var b [Bytes]byte
    28         {{- range $i := reverse .NbWordsIndexesFull}}
    29                 {{- $j := mul $i 8}}
    30                 {{- $k := sub $.NbWords 1}}
    31                 {{- $k := sub $k $i}}
    32                 {{- $jj := add $j 8}}
    33                 binary.BigEndian.PutUint64(b[{{$j}}:{{$jj}}], z[{{$k}}])
    34         {{- end}}
    35  
    36         return res.SetBytes(b[:])
    37  }
    38  
    39  {{- $noNeg := and (eq $.NbWords 1) (ltu64 (index $.Q 0) 1000000)}}
    40  // Text returns the string representation of z in the given base.
    41  // Base must be between 2 and 36, inclusive. The result uses the
    42  // lower-case letters 'a' to 'z' for digit values 10 to 35.
    43  // No prefix (such as "0x") is added to the string. If z is a nil
    44  // pointer it returns "<nil>".
    45  {{- if not $noNeg}}
    46  // If base == 10 and -z fits in a uint16 prefix "-" is added to the string.
    47  {{- end}}
    48  func (z *{{.ElementName}}) Text(base int) string {
    49  	if base < 2 || base > 36 {
    50  		panic("invalid base")
    51  	}
    52  	if z == nil {
    53  		return "<nil>"
    54  	}
    55  
    56  	const maxUint16 = 65535
    57  	{{- if eq $.NbWords 1}}
    58  		{{- if not $noNeg}}
    59  		if base == 10 {
    60  			var zzNeg {{.ElementName}}
    61  			zzNeg.Neg(z)
    62  			zzNeg.fromMont()
    63  			if zzNeg[0] <= maxUint16 && zzNeg[0] != 0 {
    64  				return "-" + strconv.FormatUint(zzNeg[0], base)
    65  			}
    66  		}
    67  		{{- end}}
    68  		zz := z.Bits()
    69  		return strconv.FormatUint(zz[0], base)
    70  	{{- else }}
    71  		if base == 10 {
    72  			var zzNeg {{.ElementName}}
    73  			zzNeg.Neg(z)
    74  			zzNeg.fromMont()
    75  			if zzNeg.FitsOnOneWord() && zzNeg[0] <= maxUint16 && zzNeg[0] != 0  {
    76  				return "-" + strconv.FormatUint(zzNeg[0], base)
    77  			}
    78  		}
    79  		zz := *z
    80  		zz.fromMont()
    81  		if zz.FitsOnOneWord() {
    82  			return strconv.FormatUint(zz[0], base)
    83  		} 
    84  		vv := pool.BigInt.Get()
    85  		r := zz.toBigInt(vv).Text(base)
    86  		pool.BigInt.Put(vv)
    87  		return r
    88  	{{- end}}
    89  }
    90  
    91  // BigInt sets and return z as a *big.Int
    92  func (z *{{.ElementName}}) BigInt(res *big.Int) *big.Int {
    93  	_z := *z
    94  	_z.fromMont()
    95  	return _z.toBigInt(res)
    96  }
    97  
    98  // ToBigIntRegular returns z as a big.Int in regular form
    99  // 
   100  // Deprecated: use BigInt(*big.Int) instead
   101  func (z {{.ElementName}}) ToBigIntRegular(res *big.Int) *big.Int {
   102  	z.fromMont()
   103  	return z.toBigInt(res)
   104  }
   105  
   106  // Bits provides access to z by returning its value as a little-endian [{{.NbWords}}]uint64 array. 
   107  // Bits is intended to support implementation of missing low-level {{.ElementName}}
   108  // functionality outside this package; it should be avoided otherwise.
   109  func (z *{{.ElementName}}) Bits() [{{.NbWords}}]uint64 {
   110  	_z := *z
   111  	fromMont(&_z)
   112  	return _z
   113  }
   114  
   115  // Bytes returns the value of z as a big-endian byte array
   116  func (z *{{.ElementName}}) Bytes() (res [Bytes]byte) {
   117  	BigEndian.PutElement(&res, *z)
   118  	return
   119  }
   120  
   121  // Marshal returns the value of z as a big-endian byte slice
   122  func (z *{{.ElementName}}) Marshal() []byte {
   123  	b := z.Bytes()
   124  	return b[:]
   125  }
   126  
   127  // Unmarshal is an alias for SetBytes, it sets z to the value of e.
   128  func (z *{{.ElementName}}) Unmarshal(e []byte) {
   129  	z.SetBytes(e)
   130  }
   131  
   132  // SetBytes interprets e as the bytes of a big-endian unsigned integer,
   133  // sets z to that value, and returns z.
   134  func (z *{{.ElementName}}) SetBytes(e []byte) *{{.ElementName}} {
   135  	if len(e) == Bytes {
   136  		// fast path
   137  		v, err := BigEndian.Element((*[Bytes]byte)(e))
   138  		if err == nil {
   139  			*z = v
   140  			return z 
   141  		}
   142  	}
   143  
   144  	// slow path.
   145  	// get a big int from our pool
   146  	vv := pool.BigInt.Get()
   147  	vv.SetBytes(e)
   148  
   149  	// set big int
   150  	z.SetBigInt(vv)
   151  
   152  	// put temporary object back in pool
   153  	pool.BigInt.Put(vv)
   154  
   155  	return z 
   156  }
   157  
   158  // SetBytesCanonical interprets e as the bytes of a big-endian {{.NbBytes}}-byte integer.
   159  // If e is not a {{.NbBytes}}-byte slice or encodes a value higher than q, 
   160  // SetBytesCanonical returns an error.
   161  func (z *{{.ElementName}}) SetBytesCanonical(e []byte) error {
   162  	if len(e) != Bytes {
   163  		return errors.New("invalid {{.PackageName}}.{{.ElementName}} encoding")
   164  	}
   165  	v, err := BigEndian.Element((*[Bytes]byte)(e))
   166  	if err != nil {
   167  		return err
   168  	}
   169  	*z = v
   170  	return nil
   171  }
   172  
   173  
   174  // SetBigInt sets z to v and returns z
   175  func (z *{{.ElementName}}) SetBigInt(v *big.Int) *{{.ElementName}} {
   176  	z.SetZero()
   177  
   178  	var zero big.Int
   179  
   180  	// fast path
   181  	c := v.Cmp(&_modulus)
   182  	if c == 0 {
   183  		// v == 0
   184  		return z
   185  	} else if c != 1 && v.Cmp(&zero) != -1 {
   186  		// 0 < v < q
   187  		return z.setBigInt(v)
   188  	}
   189  
   190  	// get temporary big int from the pool
   191  	vv := pool.BigInt.Get()
   192  
   193  	// copy input + modular reduction
   194  	vv.Mod(v, &_modulus)
   195  
   196  	// set big int byte value
   197  	z.setBigInt(vv)
   198  
   199  	// release object into pool
   200  	pool.BigInt.Put(vv)
   201  	return z
   202  }
   203  
   204  // setBigInt assumes 0 ⩽ v < q
   205  func (z *{{.ElementName}}) setBigInt(v *big.Int) *{{.ElementName}} {
   206  	vBits := v.Bits()
   207  
   208  	if bits.UintSize == 64 {
   209  		for i := 0; i < len(vBits); i++ {
   210  			z[i] = uint64(vBits[i])
   211  		}
   212  	} else {
   213  		for i := 0; i < len(vBits); i++ {
   214  			if i%2 == 0 {
   215  				z[i/2] = uint64(vBits[i])
   216  			} else {
   217  				z[i/2] |= uint64(vBits[i]) << 32
   218  			}
   219  		}
   220  	}
   221  
   222  	return z.toMont()
   223  }
   224  
   225  // SetString creates a big.Int with number and calls SetBigInt on z
   226  //
   227  // The number prefix determines the actual base: A prefix of
   228  // ''0b'' or ''0B'' selects base 2, ''0'', ''0o'' or ''0O'' selects base 8,
   229  // and ''0x'' or ''0X'' selects base 16. Otherwise, the selected base is 10
   230  // and no prefix is accepted.
   231  //
   232  // For base 16, lower and upper case letters are considered the same:
   233  // The letters 'a' to 'f' and 'A' to 'F' represent digit values 10 to 15.
   234  //
   235  // An underscore character ''_'' may appear between a base
   236  // prefix and an adjacent digit, and between successive digits; such
   237  // underscores do not change the value of the number.
   238  // Incorrect placement of underscores is reported as a panic if there
   239  // are no other errors.
   240  //
   241  // If the number is invalid this method leaves z unchanged and returns nil, error.
   242  func (z *{{.ElementName}}) SetString(number string) (*{{.ElementName}}, error) {
   243  	// get temporary big int from the pool
   244  	vv := pool.BigInt.Get()
   245  
   246  	if _, ok := vv.SetString(number, 0); !ok {
   247  		return nil, errors.New("{{.ElementName}}.SetString failed -> can't parse number into a big.Int " + number)
   248  	}
   249  
   250  	z.SetBigInt(vv)
   251  
   252  	// release object into pool
   253  	pool.BigInt.Put(vv)
   254  
   255  	return z, nil
   256  }
   257  
   258  
   259  // MarshalJSON returns json encoding of z (z.Text(10))
   260  // If z == nil, returns null
   261  func (z *{{.ElementName}}) MarshalJSON() ([]byte, error) {
   262  	if z == nil {
   263  		return []byte("null"), nil
   264  	}
   265  	const maxSafeBound = 15 // we encode it as number if it's small
   266  	s := z.Text(10)
   267  	if len(s) <= maxSafeBound {
   268  		return []byte(s), nil
   269  	}
   270  	var sbb strings.Builder
   271  	sbb.WriteByte('"')
   272  	sbb.WriteString(s)
   273  	sbb.WriteByte('"')
   274  	return []byte(sbb.String()), nil
   275  }
   276  
   277  // UnmarshalJSON accepts numbers and strings as input
   278  // See {{.ElementName}}.SetString for valid prefixes (0x, 0b, ...)
   279  func (z *{{.ElementName}}) UnmarshalJSON(data []byte) error {
   280  	s := string(data)
   281  	if len(s) > Bits*3 {
   282  		return errors.New("value too large (max = {{.ElementName}}.Bits * 3)")
   283  	}
   284  
   285  	// we accept numbers and strings, remove leading and trailing quotes if any
   286  	if len(s) > 0 && s[0] == '"' {
   287  		s = s[1:]
   288  	}
   289  	if len(s) > 0 && s[len(s)-1] == '"' {
   290  		s = s[:len(s)-1]
   291  	}
   292  
   293  	// get temporary big int from the pool
   294  	vv := pool.BigInt.Get()
   295  
   296  	if _, ok := vv.SetString(s, 0); !ok {
   297  		return errors.New("can't parse into a big.Int: " + s)
   298  	}
   299  
   300  	z.SetBigInt(vv)
   301  
   302  	// release object into pool
   303  	pool.BigInt.Put(vv)
   304  	return nil
   305  }
   306  
   307  
   308  // A ByteOrder specifies how to convert byte slices into a {{.ElementName}}
   309  type ByteOrder interface {
   310  	Element(*[Bytes]byte) ({{.ElementName}}, error)
   311  	PutElement(*[Bytes]byte, {{.ElementName}})
   312  	String() string
   313  }
   314  
   315  
   316  // BigEndian is the big-endian implementation of ByteOrder and AppendByteOrder.
   317  var BigEndian bigEndian
   318  
   319  type bigEndian struct{}
   320  
   321  // Element interpret b is a big-endian {{.NbBytes}}-byte slice.
   322  // If b encodes a value higher than q, Element returns error.
   323  func (bigEndian) Element(b *[Bytes]byte) ({{.ElementName}}, error) {
   324  	var z {{.ElementName}}
   325  	{{- range $i := reverse .NbWordsIndexesFull}}
   326  		{{- $j := mul $i 8}}
   327  		{{- $k := sub $.NbWords 1}}
   328  		{{- $k := sub $k $i}}
   329  		{{- $jj := add $j 8}}
   330  		z[{{$k}}] = binary.BigEndian.Uint64((*b)[{{$j}}:{{$jj}}])
   331  	{{- end}}
   332  
   333  	if !z.smallerThanModulus() {
   334  		return {{.ElementName}}{}, errors.New("invalid {{.PackageName}}.{{.ElementName}} encoding")
   335  	}
   336  
   337  	z.toMont()
   338  	return z, nil
   339  }
   340  
   341  func (bigEndian) PutElement(b *[Bytes]byte, e {{.ElementName}})  {
   342  	e.fromMont()
   343  
   344  	{{- range $i := reverse .NbWordsIndexesFull}}
   345  		{{- $j := mul $i 8}}
   346  		{{- $k := sub $.NbWords 1}}
   347  		{{- $k := sub $k $i}}
   348  		{{- $jj := add $j 8}}
   349  		binary.BigEndian.PutUint64((*b)[{{$j}}:{{$jj}}], e[{{$k}}])
   350  	{{- end}}
   351  }
   352  
   353  func (bigEndian) String() string { return "BigEndian" }
   354  
   355  
   356  
   357  // LittleEndian is the little-endian implementation of ByteOrder and AppendByteOrder.
   358  var LittleEndian littleEndian
   359  
   360  type littleEndian struct{}
   361  
   362  func (littleEndian) Element(b *[Bytes]byte) ({{.ElementName}}, error) {
   363  	var z {{.ElementName}}
   364  	{{- range $i := .NbWordsIndexesFull}}
   365  		{{- $j := mul $i 8}}
   366  		{{- $jj := add $j 8}}
   367  		z[{{$i}}] = binary.LittleEndian.Uint64((*b)[{{$j}}:{{$jj}}])
   368  	{{- end}}
   369  
   370  	if !z.smallerThanModulus() {
   371  		return {{.ElementName}}{}, errors.New("invalid {{.PackageName}}.{{.ElementName}} encoding")
   372  	}
   373  
   374  	z.toMont()
   375  	return z, nil
   376  }
   377  
   378  func (littleEndian) PutElement(b *[Bytes]byte, e {{.ElementName}})  {
   379  	e.fromMont()
   380  
   381  	{{- range $i := .NbWordsIndexesFull}}
   382  		{{- $j := mul $i 8}}
   383  		{{- $jj := add $j 8}}
   384  		binary.LittleEndian.PutUint64((*b)[{{$j}}:{{$jj}}], e[{{$i}}])
   385  	{{- end}}
   386  }
   387  
   388  func (littleEndian) String() string { return "LittleEndian" }
   389  
   390  
   391  
   392  
   393  `