Awesome
fp
generates prime fields, field elements and x86 optimized, high speed field operations.
Generating Field
Example commands to generate fields can be found here.
There are four generation modes.
A. Predefined Modulus
Given modulus input you get a field implementation with its precomputed constants.
# maybe you would like to generate a field for a BLS12-381 elliptic curve implementation
MODULUS=0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
go run . -output $GEN_DIR -bit 384 -opt A -modulus $MODULUS
B. Random Field
Option B helps to generate a random field with random prime modulus at desired bit length.
C. Arbitrary modulus
With this option you get a field implementation where you feed the modulus while construction of a field in runtime.
D. Generic
In generic case, field elements are unsafe pointers
. This helps us to decide size of field element and its arithmetic functions in runtime. It also helps us to represent field element with single type independent from their size. Generic field implementation is already generated.
type fieldElement = unsafe.Pointer
// Given limb size returns field element filled with zero
func newFieldElement(limbSize int) (fieldElement, error) {
switch limbSize {
case 1:
return unsafe.Pointer(&[1]uint64{}), nil
case 2:
return unsafe.Pointer(&[2]uint64{}), nil
case 3:
return unsafe.Pointer(&[3]uint64{}), nil
...
case 12:
return unsafe.Pointer(&[12]uint64{}), nil
...
...
}
Simply provide a modulus in bytes to initialize a field.
pStr := "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"
pBytes, _ := hex.DecodeString(pStr[2:])
field := newField(pBytes)
Benchmark
Benchmarked on 2,7 GHz i5 machine
Table below shows multiplication delays corresponding field sizes in bits.
128: 10.5 ns/op
192: 15.8 ns/op
256: 23.9 ns/op
320: 33.3 ns/op
384: 43.4 ns/op
448: 59.2 ns/op
512: 67.2 ns/op
576: 81.9 ns/op
640: 103 ns/op
704: 130 ns/op
768: 153 ns/op
832: 177 ns/op
896: 202 ns/op
960: 228 ns/op
1024: 256 ns/op