123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268(** Base module signature for a finite field *)moduletypeBASE=sigexceptionNot_in_fieldofBytes.ttypet(** The order of the finite field *)valorder:Z.t(** minimal number of bytes required to encode a value of the field. *)valsize_in_bytes:int(** The neutral element for the addition *)valzero:t(** The neutral element for the multiplication *)valone:t(** [is_zero x] returns [true] if [x] is the neutral element for the addition *)valis_zero:t->bool(** [is_one x] returns [true] if [x] is the neutral element for the multiplication *)valis_one:t->bool(** [random ()] returns a random element of the field. A state for the PRNG
can be given to initialize the PRNG in the requested state. If no state is
given, no initialisation is performed *)valrandom:?state:Random.State.t->unit->t(** [non_null_random ()] returns a non null random element of the field.
A state for the PRNG can be given to initialize the PRNG in the requested
state. If no state is given, no initialisation is performed *)valnon_null_random:?state:Random.State.t->unit->t(** [add a b] returns [a + b mod order] *)valadd:t->t->t(** Infix operator for [add] *)val(+):t->t->t(** [mul a b] returns [a * b mod order] *)valmul:t->t->t(** Infix operator for [mul] *)val(*):t->t->t(** [eq a b] returns [true] if [a = b mod order], else [false] *)valeq:t->t->bool(** Infix operator for [eq] *)val(=):t->t->bool(** [negate x] returns [-x mod order]. Equivalently, [negate x] returns the
unique [y] such that [x + y mod order = 0]
*)valnegate:t->t(** Infix operator for [negate] *)val(-):t->t(** [inverse_exn x] returns [x^-1] if [x] is not [0], else raise
[Division_by_zero]
*)valinverse_exn:t->t(** [inverse_opt x] returns [x^-1] if [x] is not [0] as an option, else [None] *)valinverse_opt:t->toption(** [div_exn a b] returns [a * b^-1]. Raise [Division_by_zero] if [b = zero] *)valdiv_exn:t->t->t(** [div_opt a b] returns [a * b^-1] as an option. Return [None] if [b = zero] *)valdiv_opt:t->t->toption(** Infix operator for [div_exn] *)val(/):t->t->t(** [square x] returns [x^2] *)valsquare:t->t(** [double x] returns [2x] *)valdouble:t->t(** [pow x n] returns [x^n] *)valpow:t->Z.t->t(** Infix operator for [pow] *)val(**):t->Z.t->t(** From a predefined bytes representation, construct a value t. It is not
required that to_bytes of_bytes_exn t = t.
Raise [Not_in_field] if the bytes do not represent an element in the field.
*)valof_bytes_exn:Bytes.t->t(** From a predefined bytes representation, construct a value t. It is not
required that to_bytes (Option.get (of_bytes_opt t)) = t. By default, little endian encoding
is used and the given element is modulo the prime order *)valof_bytes_opt:Bytes.t->toption(** Convert the value t to a bytes representation which can be used for
hashing for instance. It is not required that to_bytes of_bytes_exn t = t. By
default, little endian encoding is used, and length of the resulting bytes
may vary depending on the order.
*)valto_bytes:t->Bytes.tend(** Module type for prime field of the form GF(p) where p is prime *)moduletypePRIME=sigincludeBASE(** Create a value t from a predefined string representation. It is not
required that to_string of_string t = t. By default, decimal
representation of the number is used, modulo the order of the field *)valof_string:string->t(** String representation of a value t. It is not required that to_string
of_string t = t. By default, decimal representation of the number is
used *)valto_string:t->string(** [of_z x] builds an element t from the Zarith element x. [mod order] is
applied if [x > order] *)valof_z:Z.t->t(** [to_z x] builds a Zarith element, using the decimal representation.
Arithmetic on the result can be done using the modular functions on
integer *)valto_z:t->Z.tend(** Module type for prime field with additional functions to manipulate roots of unity *)moduletypePRIME_WITH_ROOT_OF_UNITY=sigincludePRIME(** Returns a nth root of unity *)valget_nth_root_of_unity:Z.t->t(** [is_nth_root_of_unity n x] returns [true] if [x] is a nth-root of unity*)valis_nth_root_of_unity:Z.t->t->boolendmoduleMakeFp(S:sigvalprime_order:Z.tend):PRIME_WITH_ROOT_OF_UNITY=structexceptionNot_in_fieldofBytes.ttypet=Z.tletorder=assert(S.prime_order>=Z.of_string"2");S.prime_orderletlog256n=logn/.log256.letsize_in_bytes=int_of_float(log256(Z.to_floatorder))+1letzero=Z.zeroletone=Z.oneletis_zeros=Z.equal(Z.eremsorder)Z.zeroletis_ones=Z.equal(Z.eremsorder)Z.oneletrandom?state()=(matchstatewithNone->()|Somes->Random.set_states);letr=Bytes.initsize_in_bytes(fun_->char_of_int(Random.int256))inZ.erem(Z.of_bits(Bytes.to_stringr))orderletnon_null_random?state()=(matchstatewithNone->()|Somes->Random.set_states);letrecaux()=letr=random()inifis_zerorthenaux()elserinaux()letaddab=Z.erem(Z.addab)orderlet(+)=addletmulab=Z.erem(Z.mulab)orderlet(*)=mulleteqab=Z.equal(Z.eremaorder)(Z.eremborder)let(=)=eqletnegatea=Z.suborderalet(-)=negateletinverse_exna=ifa=zerothenraiseDivision_by_zeroelseZ.invertaorderletinverse_opta=trySome(Z.invertaorder)withDivision_by_zero->Noneletdiv_exnab=ifb=zerothenraiseDivision_by_zeroelsemula(inverse_exnb)letdiv_optab=ifb=zerothenNoneelseSome(mula(inverse_exnb))let(/)=div_exnletsquarex=Z.mulxxletdoublex=Z.addxxlettwo_z=Z.succZ.oneletrecpowxn=ifZ.equalnZ.zerothenoneelseifis_zeroxthenzeroelseifZ.equalnZ.onethenxelseletn=Z.eremn(Z.predorder)inlet(a,r)=Z.ediv_remntwo_zinletacc=powxainletacc_square=mulaccaccinifZ.equalrZ.zerothenacc_squareelsemulacc_squarexlet(**)=pow(* Decimal representation by default *)letof_strings=Z.erem(Z.of_strings)order(* Decimal representation by default *)letto_strings=Z.to_strings(** From a predefined bytes representation, construct a value t. It is not
required that to_bytes (of_bytes_exn t)) = t. By default, little endian
encoding is used and the given element is modulo the prime order *)letof_bytes_exns=Z.erem(Z.of_bits(Bytes.to_strings))order(** From a predefined bytes representation, construct a value t. It is not
required that to_bytes (Option.get (of_bytes_opt t)) = t. By default,
little endian encoding is used and the given element is modulo the prime order *)letof_bytes_opts=Some(of_bytes_exns)(* Little endian representation *)letto_bytess=letb=Bytes.of_string(Z.to_bitss)inletres=Bytes.makesize_in_bytes'\000'inBytes.blitb0res0(min(Bytes.lengthb)size_in_bytes);resletrecget_nth_root_of_unityn=ifnot(Z.equal(Z.erem(Z.predorder)n)Z.zero)thenfailwith"n must divide the order of the multiplicate group"elseletr=random()inif(not(eqrzero))&&eq(pow(powr(Z.div(Z.predorder)n))n)onethenrelseget_nth_root_of_unitynletis_nth_root_of_unitynx=ifnot(Z.equal(Z.erem(Z.predorder)n)Z.zero)thenfailwith"n must divide the order of the multiplicate group"else(not(eqxzero))&&eq(pow(powx(Z.div(Z.predorder)n))n)oneletto_zt=tletof_zt=Z.eremtorderend