123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279(*****************************************************************************)(* *)(* 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. *)(* *)(*****************************************************************************)moduletypeStubs_sig=sigtypefr_arraytypeec_array(** [evaluation_ecfft_inplace points domain log log_degree] performs the ECFTT.
requires:
- [size p = size domain]
- [size domain = 2^log]
- [domain = [one; g; ..; g^{n-1}]] where [g] is a primitive
[n]-th root of unity and [n = 2^log] (as done by {!Domain.Stubs.compute_domain}) *)valevaluation_ecfft_inplace:ec_array->domain:fr_array->log:int->log_degree:int->unit(** [interpolation_ecfft_inplace p domain log] performs the inverse ECFFT.
requires:
- [size p = size domain]
- [size domain = 2^log]
- [domain = [one; g; ..; g^{n-1}]] where [g] is a primitive
[n]-th root of unity and [n = 2^log] (as done by {!Domain.Stubs.compute_domain}) *)valinterpolation_ecfft_inplace:ec_array->domain:fr_array->log:int->unit(** [add_arrays_inplace a b size] writes the element-wise sum of the input
vectors [a] and [b] into [a].
requires:
- [size a = size b = size] *)valadd_arrays_inplace:ec_array->ec_array->int->unit(** [mul_arrays evaluations arrays (dim1, dim2)] computes the EC point multiplication
given the scalar multipliers [evaluations] and the points [arrays].
requires:
- [size evaluations = size arrays = dim1]
- [size evaluations.(i) = size arrays.(i) = dim2] for i=0, ..., dim1-1 *)valmul_arrays:ec_arrayarray->fr_arrayarray->ec_arrayarray->int*int->unitendmoduletypeEC_carray_sig=sigincludeCarray.Carray_sigtypedomain(** [evaluation_ecfft domain points] computes the ECFFT.
[domain] can be obtained using {!Domain.build}.
The ECFFT computes the G-linear map
[G^n -> G^n :
(P_i)_{i=0,...,n-1} |-> (sum_{i=0}^{n-1} [domain.(i*j mod n)]P_i)_{j=0,...,n-1}].
where [a]P denotes the elliptic curve point multiplication.
Note:
- size of domain must be a power of two
- degree of polynomial must be strictly less than the size of domain *)valevaluation_ecfft:domain:domain->points:t->t(** [interpolation_ecfft_inplace domain points] computes the inverse ECFFT.
[domain] can be obtained using {!Domain.build}.
It is the inverse function of [evaluation_ecfft_inplace].
Note:
- size of domain must be a power of two
- size of a polynomial must be equal to size of domain *)valinterpolation_ecfft_inplace:domain:domain->points:t->unit(** [add_arrays_inplace a b] writes the element-wise sum of the input
vectors [a] and [b] into [a] *)valadd_arrays_inplace:t->t->unittypeevaluations(** [mul_arrays evaluations arrays] computes the EC point multiplication
given the scalar multipliers [evaluations] and the points [arrays] *)valmul_arrays:evaluations:evaluationsarray->arrays:tarray->tarrayendmoduleMake(EC_point:Bls12_381.CURVE)(EC_point_array:Carray.Carray_sigwithtypeelt=EC_point.t)(Stubs:Stubs_sigwithtypefr_array=Fr_carray.tandtypeec_array=EC_point_array.t):EC_carray_sigwithtypeelt=EC_point.tandtypedomain=Domain.tandtypeevaluations=Evaluations.t=structincludeEC_point_arraytypedomain=Domain.tmoduleDomain=Domain.Domain_unsafeletevaluation_ecfft~domain~points=letn_domain=Domain.lengthdomaininletres=EC_point_array.initn_domain(fun_->EC_point.(copyzero))inletdegree=EC_point_array.degreepointsinletn_domain=Domain.lengthdomaininifdegree=-1thenreselseletlog=Z.log2(Z.of_intn_domain)inifnot(Helpers.is_power_of_twon_domain)thenraise@@Invalid_argument"Size of domain should be a power of 2.";ifnot(degree<n_domain)thenraise@@Invalid_argument"Degree of poly should be strictly less than domain size.";letlog_degree=Z.log2up(Z.of_int(degree+1))inletlen=EC_point_array.lengthpointsinEC_point_array.blitpoints~src_off:0res~dst_off:0~len;Stubs.evaluation_ecfft_inplaceres~domain:(Domain.to_carraydomain)~log~log_degree;resletinterpolation_ecfft_inplace~domain~points=ifEC_point_array.degreepoints=-1then()elseletn=lengthpointsinletlog=Z.log2(Z.of_intn)inletn_domain=Domain.lengthdomaininifnot(Helpers.is_power_of_twon_domain)thenraise@@Invalid_argument"Size of domain should be a power of 2.";letn_points=lengthpointsinifnot(n_points=n_domain)thenraise@@Invalid_argument"Size of coefficients should be same as domain.";Stubs.interpolation_ecfft_inplacepoints~domain:(Domain.to_carraydomain)~logletadd_arrays_inplaceab=leta_len=lengthainletb_len=lengthbinifa_len<>b_lenthenraise(Invalid_argument"add_arrays_inplace: input arrays must have same length");Stubs.add_arrays_inplaceaba_lentypeevaluations=Evaluations.tmoduleEvaluations_unsafe=Evaluations.Evaluations_unsafeletmul_arrays~evaluations~arrays=letarrays_number=Array.lengtharraysinifarrays_number<>Array.lengthevaluationsthenraise(Invalid_argument"mul_arrays_inplace: arrays must have same length");letarray_size=lengtharrays.(0)inletres=Array.initarrays_number(fun_->allocatearray_size)inStubs.mul_arraysres(Array.mapEvaluations_unsafe.to_carrayevaluations)arrays(arrays_number,array_size);resendmoduleG1=Bls12_381.G1moduleG2=Bls12_381.G2moduleG1_Elt=structtypet=G1.t(** The size in jacobian coordinates *)letsize=G1.size_in_bytes/2*3letzero=G1.zeroletallocate()=G1.(copyzero)leteq=G1.eqendmoduleG2_Elt=structtypet=G2.t(** The size in jacobian coordinates *)letsize=G2.size_in_bytes/2*3letzero=G2.zeroletallocate()=G2.(copyzero)leteq=G2.eqendmoduleG1_array_internal=Carray.Make(G1_Elt)moduleG2_array_internal=Carray.Make(G2_Elt)moduleStubs_g1=structtypefr_array=Fr_carray.ttypeec_array=G1_array_internal.texternalevaluation_ecfft_inplace:ec_array->domain:fr_array->log:int->log_degree:int->unit="caml_bls12_381_polynomial_fft_g1_inplace_on_stubs"externalinterpolation_ecfft_inplace:ec_array->domain:fr_array->log:int->unit="caml_bls12_381_polynomial_ifft_g1_inplace_on_stubs"externaladd_arrays_inplace:ec_array->ec_array->int->unit="caml_bls12_381_polynomial_carray_g1_add_inplace_stubs"externalmul_arrays:ec_arrayarray->fr_arrayarray->ec_arrayarray->int*int->unit="caml_bls12_381_polynomial_evaluations_mul_arrays_g1_stubs"endmoduleStubs_g2=structtypefr_array=Fr_carray.ttypeec_array=G2_array_internal.texternalevaluation_ecfft_inplace:ec_array->domain:fr_array->log:int->log_degree:int->unit="caml_bls12_381_polynomial_fft_g2_inplace_on_stubs"externalinterpolation_ecfft_inplace:ec_array->domain:fr_array->log:int->unit="caml_bls12_381_polynomial_ifft_g2_inplace_on_stubs"externaladd_arrays_inplace:ec_array->ec_array->int->unit="caml_bls12_381_polynomial_carray_g2_add_inplace_stubs"externalmul_arrays:ec_arrayarray->fr_arrayarray->ec_arrayarray->int*int->unit="caml_bls12_381_polynomial_evaluations_mul_arrays_g2_stubs"endmoduleG1_carray:EC_carray_sigwithtypeelt=Bls12_381.G1.tandtypedomain=Domain.tandtypeevaluations=Evaluations.t=Make(G1)(G1_array_internal)(Stubs_g1)moduleG2_carray:EC_carray_sigwithtypeelt=Bls12_381.G2.tandtypedomain=Domain.tandtypeevaluations=Evaluations.t=Make(G2)(G2_array_internal)(Stubs_g2)