123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204(*****************************************************************************)(* *)(* MIT License *)(* Copyright (c) 2022 Nomadic Labs <contact@nomadic-labs.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)openLang_stdlibopenLang_coremoduleMake(Bound:sigtype'at=privateZ.tvalv:'at->Z.tend)=structmoduleP:sigtype'at=privateZ.t*Z.tvalmake:?unsafe:bool->Z.t->bound:'aBound.t->'atvalv:'at->Z.tvaladd:?unsafe:bool->'at->'bt->unittvaladd_left:?unsafe:bool->'at->'bt->'atvalsub_left:?unsafe:bool->'at->'bt->'atvalsucc:?unsafe:bool->'at->'atvalrandom:?maxv:Z.t->'aBound.t->'atvalcheck:'at->boolvalf:'at->unittend=structtype'at=Z.t*Z.tletmake?(unsafe=false)v~bound=letbound=(bound:'aBound.t:>Z.t)inassert(bound<Bls12_381.Fr.order);ifnotunsafethenassert(v<bound);(v,bound)letv(x,_)=xletadd?(unsafe=false)(a,bnd)(b,bnd')=letn_bnd=Z.(bnd+bnd')inifnotunsafethenassert(n_bnd<Bls12_381.Fr.order);letr=Z.addabinifnotunsafethenassert(Z.zero<=r&&r<n_bnd);(r,n_bnd)letadd_left?(unsafe=false)(a,bnd)(b,bnd')=ifnotunsafethenassert(Z.(bnd+bnd'<Bls12_381.Fr.order));letr=Z.addabinifnotunsafethenassert(Z.zero<=r&&r<bnd);(r,bnd)letsub_left?(unsafe=false)(a,bnd)(b,bnd')=ifnotunsafethenassert(Z.(bnd+bnd'<Bls12_381.Fr.order));letr=Z.subabinifnotunsafethenassert(Z.zero<=r&&r<bnd);(r,bnd)letsucc?(unsafe=false)(a,bnd)=ifnotunsafethenassert(Z.(bnd+one<Bls12_381.Fr.order));letr=Z.succainifnotunsafethenassert(Z.zero<=r&&r<bnd);(r,bnd)letrandom?maxvbound=letrandom_zbound=Random.int64(Z.to_int64bound)|>Z.of_int64inletbound=(bound:'aBound.t:>Z.t)inletmaxv=matchmaxvwith|None->bound|Somemaxv->assert(maxv<=bound);maxvin(random_zmaxv,bound)letcheck(v,bound)=Z.(v>=zero&&v<bound)letfx=xendmoduleV(L:LIB):sigopenLtype'at=privatescalarrepr*Z.tvalmake:scalarrepr->bound:'aBound.t->'atL.tvalmake_unsafe:scalarrepr->bound:'aBound.t->'atvalsucc:?unsafe:bool->'at->'atL.tvaladd:?unsafe:bool->'at->'bt->'ctL.tvaladd_left:?unsafe:bool->'at->'bt->'atL.tvalsub_left:?unsafe:bool->'at->'bt->'atL.tvalf:'at->unittend=structopenLtype'at=scalarrepr*Z.tletmakew~bound=letbound=(bound:'aBound.t:>Z.t)inassert(bound<Bls12_381.Fr.order);with_bool_check(Num.is_upper_boundedw~bound)>*ret(w,bound)letmake_unsafew~bound=(w,Bound.vbound)letadd?(unsafe=false)(a,bound)(b,bound')=assert(Z.(bound+bound'<Bls12_381.Fr.order));let*r=Num.addabinifunsafethenret(r,Z.addboundbound')elsewith_bool_check(Num.is_upper_bounded_unsafer~bound:(Z.addboundbound'))>*ret(r,Z.addboundbound')letadd_left?(unsafe=false)(a,bound)(b,bound')=assert(Z.(bound+bound'<Bls12_381.Fr.order));let*r=Num.addabinletnb_bits=Z.(numbits(addboundbound'))inifunsafethenret(r,bound)elsewith_bool_check(Num.is_upper_bounded_unsafe~nb_bits~boundr)>*ret(r,bound)letsub_left?(unsafe=false)(a,bound)(b,bound')=assert(Z.(bound+bound'<Bls12_381.Fr.order));let*r=Num.add~qr:S.moneabinifunsafethenret(r,bound)elsewith_bool_check(Num.geq(a,bound)(b,bound'))>*ret(r,bound)letsucc?(unsafe=false)(a,bound)=assert(Z.(bound+one<Bls12_381.Fr.order));let*r=Num.add_constantS.oneainletnb_bits=Z.(numbits(succbound))inifunsafethenret(r,bound)elsewith_bool_check(Num.is_upper_bounded_unsafe~nb_bits~boundr)>*ret(r,bound)letfx=xendmoduleEncoding(L:LIB)=structopenLmoduleVL=V(L)openL.Encodingstypebound_check_safety=Safe|Unsafe|NoCheckletencoding~safety(bound:'aBound.t):('aP.t,'aVL.t,_)encoding=letz_bound=Bound.vboundinletf=matchsafetywith|Safe->with_implicit_bool_check(Num.is_upper_bounded~bound:z_bound)|Unsafe->with_implicit_bool_check(Num.is_upper_bounded_unsafe~bound:z_bound)|NoCheck->Fun.idinf@@conv(fun(x:'aVL.t)->letw,b=(x:'aVL.t:>scalarrepr*Z.t)inassert(z_bound=b);w)(funw->VL.make_unsafew~bound)(fun(x:'aP.t)->letv,_=(x:'aP.t:>Z.t*Z.t)inS.of_zv)(funv->P.make~unsafe:true(S.to_zv)~bound)scalar_encodingendend