123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233(** General module signature for a finite field *)moduletypeT=sigtypetvalorder:Z.t(** The order of the finite field *)valsize_in_bytes:int(** minimal number of bytes required to encode a value of the field. *)valzero:t(** The neutral element for the addition *)valone:t(** The neutral element for the multiplication *)valis_zero:t->bool(** [is_zero x] returns [true] if [x] is the neutral element for the addition *)valis_one:t->bool(** [is_one x] returns [true] if [x] is the neutral element for the multiplication *)valrandom:unit->t(** [random ()] returns a random element of the field *)valnon_null_random:unit->t(** [non_null_random ()] returns a non null random element of the field *)valadd:t->t->t(** [add a b] returns [a + b mod order] *)val(+):t->t->t(** Infix operator for [add] *)valmul:t->t->t(** [mul a b] returns [a * b mod order] *)val(*):t->t->t(** Infix operator for [mul] *)valeq:t->t->bool(** [eq a b] returns [true] if [a = b mod order], else [false] *)val(=):t->t->bool(** Infix operator for [eq] *)valnegate:t->t(** [negate x] returns [-x mod order]. Equivalently, [negate x] returns the
unique [y] such that [x + y mod order = 0]
*)val(-):t->t(** Infix operator for [negate] *)valinverse_exn:t->t(** [inverse_exn x] returns [x^-1] if [x] is not [0], else raise
[Division_by_zero]
*)valinverse_opt:t->toption(** [inverse_opt x] returns [x^-1] if [x] is not [0] as an option, else [None] *)valdiv_exn:t->t->t(** [div_exn a b] returns [a * b^-1]. Raise [Division_by_zero] if [b = zero] *)valdiv_opt:t->t->toption(** [div_opt a b] returns [a * b^-1] as an option. Return [None] if [b = zero] *)val(/):t->t->t(** Infix operator for [div_exn] *)valsquare:t->t(** [square x] returns [x^2] *)valdouble:t->t(** [double x] returns [2x] *)valpow:t->Z.t->t(** [pow x n] returns [x^n] *)val(**):t->Z.t->t(** Infix operator for [pow] *)valof_string:string->t(** 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 *)valto_string:t->string(** 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 *)valof_bytes:Bytes.t->t(** From a predefined bytes representation, construct a value t. It is not
required that to_bytes of_bytes t = t. By default, little endian encoding
is used and the given element is modulo the prime order *)valto_bytes:t->Bytes.t(** 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 t = t. By
default, little endian encoding is used, and length of the resulting bytes
may vary depending on the order.
*)valget_nth_root_of_unity:Z.t->t(** Returns a nth root of unity *)valis_nth_root_of_unity:Z.t->t->bool(** [is_nth_root_of_unity n x] returns [true] if [x] is a nth-root of unity*)valof_z:Z.t->t(** [of_z x] builds an element t from the Zarith element x. [mod order] is
applied if [x > order] *)valto_z:t->Z.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 *)endmoduleMakeFp(S:sigvalprime_order:Z.tend):T=structtypet=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()=Random.self_init();letr=Bytes.initsize_in_bytes(fun_->char_of_int(Random.int256))inZ.erem(Z.of_bits(Bytes.to_stringr))orderletrecnon_null_random()=letr=random()inifis_zerorthennon_null_random()elserletaddab=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(* Bytes must be in little endian *)letof_bytess=Z.erem(Z.of_bits(Bytes.to_strings))order(* Little endian representation *)letto_bytess=letb=Bytes.of_string(Z.to_bitss)inletres=Bytes.createsize_in_bytesinBytes.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