123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978openOcaml_intrinsics_kernel.Conditional.UnboxedmoduleF=Base.FloatmoduleA=Base.ArraymoduleFA=Float_arraytypet=float#moduleBoxed=Core.Floatletglobalize(local_t):t=texternalof_float:(float[@local_opt])->float#@@portable="%unbox_float"externalto_float:float#->(float[@local_opt])@@portable="%box_float"(* Note about the implementation strategy:
Most functions in this file are implemented by boxing the float, calling the equivalent
function on boxed floats, and then unboxing the result. This may seem surprising: isn't
the point of unboxed types to avoid boxes? But it's fine; the compiler's middle-end
will reliably eliminate these boxing and unboxing steps, and the testsuite checks there
are no allocations here. If you add new functions, you should add similar tests.
Why is it done this way? Just because it was less work than adding many new primitives
to the compiler. But it is likely we will do that work, one day.
*)moduleShared_derived=structlet%template[@alloca=(heap,stack)][@inline]sexp_of_tt:Base.Sexp.t=(F.sexp_of_t[@alloca][@inlinedhint])(to_floatt)[@exclave_if_stacka];;let[@inline]t_of_sexpsexp:t=of_float((F.t_of_sexp[@inlinedhint])sexp)lett_sexp_grammar=Sexplib0.Sexp_grammar.coerceF.t_sexp_grammarletbin_shape_t=Bin_prot_unboxed_numbers.Float_u.bin_shape_t[%%template[@@@mode.defaultm=(global,local)]let[@inlinealways]bin_size_tt=(Bin_prot_unboxed_numbers.Float_u.bin_size_t[@modem][@inlined])t;;let[@inlinealways]bin_write_tbuf~post=(Bin_prot_unboxed_numbers.Float_u.bin_write_t[@modem][@inlined])buf~post;;]let[@inlinealways]bin_read_tbuf~pos_ref=(Bin_prot_unboxed_numbers.Float_u.bin_read_t[@inlined])buf~pos_ref;;let__bin_read_t__=Bin_prot_unboxed_numbers.Float_u.__bin_read_t__letbin_writer_t=Bin_prot_unboxed_numbers.Float_u.bin_writer_tletbin_reader_t=Bin_prot_unboxed_numbers.Float_u.bin_reader_tletbin_t=Bin_prot_unboxed_numbers.Float_u.bin_tlet[@inline]hash_fold_tstatet=(F.hash_fold_t[@inlinedhint])state(to_floatt)let[@inline]hasht=(F.hash[@inlinedhint])(to_floatt)lettyperep_of_t=Typerep_lib.Std.Typerep.Float_ulettypename_of_t=Typerep_lib.Std.typename_of_float_ulet[@inline]to_stringt:string=(F.to_string[@inlinedhint])(to_floatt)let[@inline]of_strings:t=of_float((F.of_string[@inlinedhint])s)[%%template[@@@mode.defaultm=(global,local)]let[@inline][@zero_alloc]equalt1t2:bool=F.equal(to_floatt1)(to_floatt2)let[@inline][@zero_alloc]comparet1t2:int=F.compare(to_floatt1)(to_floatt2)]endincludeShared_derivedlet[@inline]ascendingt1t2:int=(F.ascending[@inlinedhint])(to_floatt1)(to_floatt2);;let[@inline]descendingt1t2:int=(F.descending[@inlinedhint])(to_floatt1)(to_floatt2);;let[@inline]betweent~low~high:bool=(F.between[@inlinedhint])(to_floatt)~low:(to_floatlow)~high:(to_floathigh);;let[@inline][@zero_allocstrict]clamp_exnt~min~max:t=of_float((F.clamp_exn[@inlinedhint])(to_floatt)~min:(to_floatmin)~max:(to_floatmax));;let[@inline]ppppft:unit=(F.pp[@inlinedhint])ppf(to_floatt)let[@inline]invariantt:unit=(F.invariant[@inlinedhint])(to_floatt)letnan:t=of_floatF.nanletinfinity:t=of_floatF.infinityletneg_infinity:t=of_floatF.neg_infinityletmax_value:t=of_floatF.max_valueletmin_value:t=of_floatF.min_valueletzero:t=of_floatF.zeroletone:t=of_floatF.oneletminus_one:t=of_floatF.minus_oneletpi:t=of_floatF.piletsqrt_pi:t=of_floatF.sqrt_piletsqrt_2pi:t=of_floatF.sqrt_2pileteuler_gamma_constant:t=of_floatF.euler_gamma_constantletepsilon_float:t=of_floatF.epsilon_floatletmax_finite_value:t=of_floatF.max_finite_valueletmin_positive_subnormal_value:t=of_floatF.min_positive_subnormal_valueletmin_positive_normal_value:t=of_floatF.min_positive_normal_valuelet[@inline]to_int64_preserve_ordert:int64option=(F.to_int64_preserve_order[@inlinedhint])(to_floatt);;let[@inline]to_int64_preserve_order_exnt:int64=(F.to_int64_preserve_order_exn[@inlinedhint])(to_floatt);;let[@inline]of_int64_preserve_orderi:t=of_float((F.of_int64_preserve_order[@inlinedhint])i);;let[@inline]one_ulpudt:t=of_float((F.one_ulp[@inlinedhint])ud(to_floatt))let[@inline][@zero_alloc]to_intt:int=(F.to_int[@inlinedhint])(to_floatt)let[@inline][@zero_alloc]to_int_uncheckedt:int=(Base.Int.of_float_unchecked[@inlinedhint])(to_floatt);;let[@inline]truncatet:int=Stdlib.truncate(to_floatt)let[@inline]of_int63i:t=of_float((F.of_int63[@inlinedhint])i)[@@zero_alloc]let[@inline]of_int64i:t=of_float((F.of_int64[@inlinedhint])i)let[@inline]to_int64t:int64=(F.to_int64[@inlinedhint])(to_floatt)externalunbox_f32:(float32[@local_opt])->float32#@@portable="%unbox_float32"externalbox_f32:float32#->(float32[@local_opt])@@portable="%box_float32"externalfloat32_of_float:local_float->(float32[@local_opt])@@portable="%float32offloat"externalfloat_of_float32:local_float32->(float[@local_opt])@@portable="%floatoffloat32"let[@inline][@zero_alloc]to_float32_ut:float32#=unbox_f32(float32_of_float(to_floatt));;let[@inline][@zero_alloc]of_float32_uf:t=of_float(float_of_float32(box_f32f))let[@inline]round?dirt:t=of_float((F.round[@inlinedhint])?dir(to_floatt))let[@inline]iround?dirt:intoption=(F.iround[@inlinedhint])?dir(to_floatt)let[@inline]iround_exn?dirt:int=(F.iround_exn[@inlinedhint])?dir(to_floatt)let[@inline][@zero_allocassume_unless_opt]round_towards_zerot:t=of_float((F.round_towards_zero[@inlinedhint])(to_floatt));;let[@inline]round_downt:t=of_float((F.round_down[@inlinedhint])(to_floatt))let[@inline]round_upt:t=of_float((F.round_up[@inlinedhint])(to_floatt))(** Rounds half integers up. *)let[@inline][@zero_allocassume_unless_opt]round_nearestt:t=of_float((F.round_nearest[@inlinedhint])(to_floatt));;(** Rounds half integers to the even integer. *)let[@inline][@zero_allocassume_unless_opt]round_nearest_half_to_event:t=of_float((F.round_nearest_half_to_even[@inlinedhint])(to_floatt));;let[@inline]iround_towards_zerot:intoption=(F.iround_towards_zero[@inlinedhint])(to_floatt);;let[@inline]iround_downt:intoption=(F.iround_down[@inlinedhint])(to_floatt)let[@inline]iround_upt:intoption=(F.iround_up[@inlinedhint])(to_floatt)let[@inline]iround_nearestt:intoption=(F.iround_nearest[@inlinedhint])(to_floatt);;let[@inline]iround_towards_zero_or_nullt:intor_null=(F.iround_towards_zero_or_null[@inlinedhint])(to_floatt);;let[@inline]iround_down_or_nullt:intor_null=(F.iround_down_or_null[@inlinedhint])(to_floatt);;let[@inline]iround_up_or_nullt:intor_null=(F.iround_up_or_null[@inlinedhint])(to_floatt);;let[@inline]iround_nearest_or_nullt:intor_null=(F.iround_nearest_or_null[@inlinedhint])(to_floatt);;let[@inline]iround_towards_zero_exnt:int=(F.iround_towards_zero_exn[@inlinedhint])(to_floatt);;let[@inline]iround_down_exnt:int=(F.iround_down_exn[@inlinedhint])(to_floatt)let[@inline]iround_up_exnt:int=(F.iround_up_exn[@inlinedhint])(to_floatt)let[@inline]iround_nearest_exnt:int=(F.iround_nearest_exn[@inlinedhint])(to_floatt);;let[@inline]int63_round_down_exnt:Base.Int63.t=(F.int63_round_down_exn[@inlinedhint])(to_floatt);;let[@inline]int63_round_up_exnt:Base.Int63.t=(F.int63_round_up_exn[@inlinedhint])(to_floatt);;let[@inline]int63_round_nearest_exnt:Base.Int63.t=(F.int63_round_nearest_exn[@inlinedhint])(to_floatt)[@@zero_alloc];;letiround_lbound=of_floatF.iround_lboundletiround_ubound=of_floatF.iround_uboundletint63_round_lbound=of_floatF.int63_round_lboundletint63_round_ubound=of_floatF.int63_round_uboundlet[@inline]round_significantt~significant_digits:t=of_float((F.round_significant[@inlinedhint])(to_floatt)~significant_digits);;let[@inline]round_decimalt~decimal_digits:t=of_float((F.round_decimal[@inlinedhint])(to_floatt)~decimal_digits);;let[@inline][@zero_alloc]is_nant:bool=(F.is_nan[@inlinedhint])(to_floatt)let[@inline][@zero_alloc]is_inft:bool=(F.is_inf[@inlinedhint])(to_floatt)let[@inline][@zero_alloc]is_finitet:bool=(F.is_finite[@inlinedhint])(to_floatt)let[@inline][@zero_alloc]is_integert:bool=(F.is_integer[@inlinedhint])(to_floatt);;let[@inline][@zero_alloc]is_positivet:bool=(F.is_positive[@inlinedhint])(to_floatt);;let[@inline][@zero_alloc]is_non_negativet:bool=(F.is_non_negative[@inlinedhint])(to_floatt);;let[@inline][@zero_alloc]is_negativet:bool=(F.is_negative[@inlinedhint])(to_floatt);;let[@inline][@zero_alloc]is_non_positivet:bool=(F.is_non_positive[@inlinedhint])(to_floatt);;let%template[@inline][@zero_alloc]min_inant1t2:t=of_float((F.min_inan[@modelocal][@inlinedhint])(to_floatt1)(to_floatt2));;let%template[@inline][@zero_alloc]max_inant1t2:t=of_float((F.max_inan[@modelocal][@inlinedhint])(to_floatt1)(to_floatt2));;let[@inline][@zero_alloc]mod_floatt1t2:t=of_float(F.mod_float(to_floatt1)(to_floatt2));;let[@inline][@zero_alloc]addt1t2:t=of_float(F.add(to_floatt1)(to_floatt2))let[@inline][@zero_alloc]subt1t2:t=of_float(F.sub(to_floatt1)(to_floatt2))let[@inline][@zero_alloc]scalet1t2:t=of_float(F.scale(to_floatt1)(to_floatt2));;moduleO=structexternalunbox:(float[@local_opt])->float#@@portable="%unbox_float"externalbox:float#->(float[@local_opt])@@portable="%box_float"let[@inline][@zero_allocstrict](+)t1t2:t=of_float(F.O.(+)(to_floatt1)(to_floatt2));;let[@inline][@zero_allocstrict](-)t1t2:t=of_float(F.O.(-)(to_floatt1)(to_floatt2));;let[@inline][@zero_allocstrict](*)t1t2:t=of_float(F.O.(*)(to_floatt1)(to_floatt2));;let[@inline][@zero_allocstrict](/)t1t2:t=of_float(F.O.(/)(to_floatt1)(to_floatt2));;let[@inline](%)t1t2:t=of_float(F.O.(%)(to_floatt1)(to_floatt2))let[@inline][@zero_allocstrict](**)t1t2:t=of_float(F.O.(**)(to_floatt1)(to_floatt2));;let[@inline][@zero_allocstrict](~-)t:t=of_float(F.O.(~-)(to_floatt))let[@inline][@zero_allocstrict](>=)t1t2:bool=F.O.(>=)(to_floatt1)(to_floatt2);;let[@inline][@zero_allocstrict](<=)t1t2:bool=F.O.(<=)(to_floatt1)(to_floatt2);;let[@inline][@zero_allocstrict](=)t1t2:bool=F.O.(=)(to_floatt1)(to_floatt2);;let[@inline][@zero_allocstrict](>)t1t2:bool=F.O.(>)(to_floatt1)(to_floatt2);;let[@inline][@zero_allocstrict](<)t1t2:bool=F.O.(<)(to_floatt1)(to_floatt2);;let[@inline][@zero_allocstrict](<>)t1t2:bool=F.O.(<>)(to_floatt1)(to_floatt2);;let[@inline][@zero_allocstrict]abst:t=of_float(F.O.abs(to_floatt))let[@inline][@zero_allocstrict]negt:t=of_float(F.O.neg(to_floatt))let[@inline][@zero_allocstrict]of_inti:t=of_float((F.O.of_int[@inlinedhint])i);;endincludeOmoduleO_dot=structlet[@inline][@zero_alloc](+.)t1t2:t=of_float(F.O_dot.(+.)(to_floatt1)(to_floatt2));;let[@inline][@zero_alloc](-.)t1t2:t=of_float(F.O_dot.(-.)(to_floatt1)(to_floatt2));;let[@inline][@zero_alloc](*.)t1t2:t=of_float(F.O_dot.(*.)(to_floatt1)(to_floatt2));;let[@inline][@zero_alloc](/.)t1t2:t=of_float(F.O_dot.(/.)(to_floatt1)(to_floatt2));;let[@inline](%.)t1t2:t=of_float(F.O_dot.(%.)(to_floatt1)(to_floatt2))let[@inline][@zero_alloc](**.)t1t2:t=of_float(F.O_dot.(**.)(to_floatt1)(to_floatt2));;let[@inline][@zero_alloc](~-.)t:t=of_float(F.O_dot.(~-.)(to_floatt))endlet[@inline]to_string_hum?delimiter?decimals?strip_zero?explicit_plust:string=(F.to_string_hum[@inlinedhint])?delimiter?decimals?strip_zero?explicit_plus(to_floatt);;let[@inline]to_padded_compact_stringt:string=(F.to_padded_compact_string[@inlinedhint])(to_floatt);;let[@inline]to_padded_compact_string_customt?prefix~kilo~mega~giga~tera?peta():string=(F.to_padded_compact_string_custom[@inlinedhint])(to_floatt)?prefix~kilo~mega~giga~tera?peta();;let[@inline]int_powti:t=of_float((F.int_pow[@inlinedhint])(to_floatt)i)let[@inline]squaret:t=of_float((F.square[@inlinedhint])(to_floatt))let[@inline]ldexpti:t=of_float(F.ldexp(to_floatt)i)let[@inline]log10t:t=of_float(F.log10(to_floatt))let[@inline]log2t:t=of_float(F.log2(to_floatt))let[@inline]expm1t:t=of_float(F.expm1(to_floatt))let[@inline]log1pt:t=of_float(F.log1p(to_floatt))let[@inline]copysignt1t2:t=of_float(F.copysign(to_floatt1)(to_floatt2))let[@inline]cost=of_float(F.cos(to_floatt))let[@inline]sint:t=of_float(F.sin(to_floatt))let[@inline]tant:t=of_float(F.tan(to_floatt))let[@inline]acost:t=of_float(F.acos(to_floatt))let[@inline]asint:t=of_float(F.asin(to_floatt))let[@inline]atant:t=of_float(F.atan(to_floatt))let[@inline]atan2t1t2:t=of_float(F.atan2(to_floatt1)(to_floatt2))let[@inline]hypott1t2:t=of_float(F.hypot(to_floatt1)(to_floatt2))let[@inline]cosht:t=of_float(F.cosh(to_floatt))let[@inline]sinht:t=of_float(F.sinh(to_floatt))let[@inline]tanht:t=of_float(F.tanh(to_floatt))let[@inline]acosht:t=of_float(F.acosh(to_floatt))let[@inline]asinht:t=of_float(F.asinh(to_floatt))let[@inline]atanht:t=of_float(F.atanh(to_floatt))let[@inline]sqrtt:t=of_float(F.sqrt(to_floatt))let[@inline]cbrtt:t=of_float(F.cbrt(to_floatt))let[@inline]expt:t=of_float(F.exp(to_floatt))let[@inline]logt:t=of_float(F.log(to_floatt))moduleClass=F.Classlet[@inline]classifyt:Class.t=(F.classify[@inlinedhint])(to_floatt)let[@inline]signt:Base.Sign.t=(F.sign[@inlinedhint])(to_floatt)[@alert"-deprecated"];;let[@inline]sign_exnt:Base.Sign.t=(F.sign_exn[@inlinedhint])(to_floatt)let[@inline]sign_or_nant:Base.Sign_or_nan.t=(F.sign_or_nan[@inlinedhint])(to_floatt);;let[@inline]create_ieee_exn~negative~exponent~mantissa:t=of_float((F.create_ieee_exn[@inlinedhint])~negative~exponent~mantissa);;let[@inline]ieee_negativet:bool=(F.ieee_negative[@inlinedhint])(to_floatt)let[@inline]ieee_exponentt:int=(F.ieee_exponent[@inlinedhint])(to_floatt)let[@inline]ieee_mantissat:Base.Int63.t=(F.ieee_mantissa[@inlinedhint])(to_floatt);;letvalidate_ordinaryt=Core.Validate.of_error_opt(matchclassifytwith|Normal|Subnormal|Zero->None|Infinite->Some"value is infinite"|Nan->Some"value is NaN");;letvalidate_not_nant=Core.Validate.of_error_opt(matchclassifytwith|Normal|Subnormal|Zero|Infinite->None|Nan->Some"value is NaN");;letvalidate_bounded~(lower:(tBase.Maybe_bound.t[@kindfloat64]))~(upper:(tBase.Maybe_bound.t[@kindfloat64]))t=ifnot((Base.Maybe_bound.is_lower_bound[@kindfloat64])lower~of_:t~compare)then(matchlowerwith|Unbounded->assertfalse|Inclincl->Core.Validate.fail[%string"value %{to_string t} < bound %{to_string incl}"]|Exclexcl->Core.Validate.fail[%string"value %{to_string t} <= bound %{to_string excl}"])elseifnot((Base.Maybe_bound.is_upper_bound[@kindfloat64])upper~of_:t~compare)then(matchupperwith|Unbounded->assertfalse|Inclincl->Core.Validate.fail[%string"value %{to_string t} > bound %{to_string incl}"]|Exclexcl->Core.Validate.fail[%string"value %{to_string t} >= bound %{to_string excl}"])elseCore.Validate.pass;;letvalidate_bound~min~maxt=Core.Validate.first_failure(validate_ordinaryt)(validate_bounded~lower:min~upper:maxt);;letvalidate_lbound~mint=validate_bound~min~max:(Base.Maybe_bound.Unbounded:(tBase.Maybe_bound.t[@kindfloat64]))t;;letvalidate_ubound~maxt=validate_bound~min:(Base.Maybe_bound.Unbounded:(tBase.Maybe_bound.t[@kindfloat64]))~maxt;;letexcl_zero:(float#Base.Maybe_bound.t[@kindfloat64])=Base.Maybe_bound.Excl#0.letincl_zero:(float#Base.Maybe_bound.t[@kindfloat64])=Base.Maybe_bound.Incl#0.letunbounded:(tBase.Maybe_bound.t[@kindfloat64])=Base.Maybe_bound.Unboundedletvalidate_positivet=Core.Validate.first_failure(validate_not_nant)(validate_bounded~lower:excl_zero~upper:unboundedt);;letvalidate_non_negativet=Core.Validate.first_failure(validate_not_nant)(validate_bounded~lower:incl_zero~upper:unboundedt);;letvalidate_negativet=Core.Validate.first_failure(validate_not_nant)(validate_bounded~lower:unbounded~upper:excl_zerot);;letvalidate_non_positivet=Core.Validate.first_failure(validate_not_nant)(validate_bounded~lower:unbounded~upper:incl_zerot);;externalbox_int64:int64#->(int64[@local_opt])@@portable="%box_int64"externalunbox_int64:(int64[@local_opt])->int64#@@portable="%unbox_int64"let[@inline]to_bitsx=Base.Int64.bits_of_float(to_floatx)|>unbox_int64let[@inline]of_bitsx=Base.Int64.float_of_bits(box_int64x)|>of_floatlet[@inline][@zero_alloc]selectb(ifso:t)(ifnot:t):t=select_int64b(to_bitsifso)(to_bitsifnot)|>of_bits;;let[@inline][@zero_alloc]first_non_nan(x:t)(y:t):t=select(is_nanx)yx(* Both of these implementations are the same up to direction.
[if (x < y) then x else y] is the correct min, except that if either is nan we get y
(because comparisons with nan are false). If y is nan, that's correct. If x is nan, we
need to pick it, so explicitly test that.
Implement that branchlessly with [select]. The only weird thing here is that we want to
do two selects, but not pass back and forth to [int64] twice, so we write out the
selects in int64-space.
*)let[@inline][@zero_alloc]min(x:t)(y:t):t=letxb=to_bitsxinletyb=to_bitsyinletminb=select_int64(x<y)xbybinselect_int64(is_nanx)xbminb|>of_bits;;let[@inline][@zero_alloc]max(x:t)(y:t):t=letxb=to_bitsxinletyb=to_bitsyinletmaxb=select_int64(x>y)xbybinselect_int64(is_nanx)xbmaxb|>of_bits;;moduletypeArray=sigtypeelt:float64typetvalget:local_t->int->elt[@@zero_alloc]valset:local_t->int->elt->unit[@@zero_alloc]valunsafe_get:local_t->int->elt[@@zero_alloc]valunsafe_set:local_t->int->elt->unit[@@zero_alloc]valcreate:len:int->elt->tvallength:local_t->intvalunsafe_blit:src:local_t->src_pos:int->dst:local_t->dst_pos:int->len:int->unitvalcompare:t->t->intvalglobalize:local_t->tvalcopy:t->tvalt_of_sexp:Core.Sexp.t->t@@portablevalsexp_of_t:t->Core.Sexp.t@@portablevalcustom_sexp_of_t:(elt->Core.Sexp.t)->t->Core.Sexp.tvalcustom_t_of_sexp:(Core.Sexp.t->elt)->Core.Sexp.t->tvalinit:int->f:(int->elt)->tvaliter:t->f:(elt->unit)->unitvaliteri:t->f:(int->elt->unit)->unitval%templateto_float_u_array:t@m->eltarray@m[@@modem=(local,global)]val%templateof_float_u_array:eltarray@m->t@m[@@modem=(local,global)]endmoduleArray=structtypet=Float_array.t[@@derivingbin_io,globalize]let[@zero_allocassume_unless_opt]getai:float#=of_float(FA.getai)let[@zero_allocassume_unless_opt]setait:unit=FA.setai(to_floatt)let[@zero_allocassume_unless_opt]unsafe_getai:float#=of_float(FA.unsafe_getai);;let[@zero_allocassume_unless_opt]unsafe_setait:unit=FA.unsafe_setai(to_floatt);;letcreate~lent:t=FA.create~len(to_floatt)letinitlen~f=(FA.init[@inlinedhint])len~f:(fun[@inline]i->fi|>to_float)letlength=FA.lengthletcopy=FA.copyletunsafe_blit=FA.unsafe_blitlett_of_sexp=FA.t_of_sexpletsexp_of_t=FA.sexp_of_tletcompare=FA.compare(* The use of %identity, as opposed to %obj_magic, is safe because the internal type
system used by the compiler's middle-end treats these two types identically (this is
a stronger requirement than just that they have the same runtime representation). *)externalto_float_u_array_external:(t[@local_opt])->(float#array[@local_opt])@@portable="%identity"externalof_float_u_array_external:(float#array[@local_opt])->(t[@local_opt])@@portable="%identity"let%expect_test"[Float_array.t] is the same as [float# array], so [%identity] is safe"=lettag_float_array=Obj.tag(Obj.repr(Float_array.create~len:11.))inlettag_float_u_array=Obj.tag(Obj.repr[|#1.|])inassert(Int.equaltag_float_arraytag_float_u_array);print_endline(Int.to_stringtag_float_array);[%expect{| 254 |}];;let%templateto_float_u_array=to_float_u_array_external[@@modem=(local,global)]let%templateof_float_u_array=of_float_u_array_external[@@modem=(local,global)]letcustom_sexp_of_tsexp_of_at=letsexp_of_aa=sexp_of_a(of_floata)inFA.custom_sexp_of_tsexp_of_at;;letcustom_t_of_sexpa_of_sexpt=leta_of_sexpsexp=to_float(a_of_sexpsexp)inFA.custom_t_of_sexpa_of_sexpt;;letitert~f=(FA.iter[@inlinedhint])t~f:(fun[@inline]x->f(of_floatx))letiterit~f=(FA.iteri[@inlinedhint])t~f:(fun[@inline]ix->fi(of_floatx))modulePermissioned=struct(* Note: Perms are from in [Core] so this [Permissioned] module will need to be placed
into the Core part when this gets added to base/core. *)type-'permst='permsFloat_array.Permissioned.tlet[@zero_allocassume_unless_opt]getai:float#=of_float(FA.Permissioned.getai);;let[@zero_allocassume_unless_opt]setait:unit=FA.Permissioned.setai(to_floatt);;let[@zero_allocassume_unless_opt]unsafe_getai:float#=of_float(FA.Permissioned.unsafe_getai);;let[@zero_allocassume_unless_opt]unsafe_setait:unit=FA.Permissioned.unsafe_setai(to_floatt);;endendmodulePolymorphic_array_helpers=structletgetai:float#=of_float(A.getai)letsetait:unit=A.setai(to_floatt)letunsafe_getai:float#=of_float(A.unsafe_getai)letunsafe_setait:unit=A.unsafe_setai(to_floatt)endmoduletypeRef=Ref_intf.TmoduleRef=structtypenonrect={mutablecontents:t}let[@inline][@zero_alloc]gett=t.contentslet[@inline][@zero_alloc]settx=t.contents<-xlet[@inline][@zero_alloc]addtx=sett(gett+x)let[@inline]createcontents={contents}let[@inline][@zero_alloc]create_localcontents=exclave_{contents}let[@inline]create_zero()=create#0.0moduleO=structlet[@inline][@zero_alloc]refx=exclave_create_localxlet[@inline][@zero_alloc](!)t=gettlet[@inline][@zero_alloc](:=)tx=settxlet[@inline][@zero_alloc](+=)tx=t:=!t+xendendletnumber_of_exponent_bits=11letnumber_of_mantissa_bits=52letsign_mask():int64#=#0x8000_0000_0000_0000Llet%test_=letshift:int=Int.addnumber_of_mantissa_bitsnumber_of_exponent_bitsinInt64_u.(sign_mask()=#1Llslshift);;includestructopenBase_quickchecklet%templatequickcheck_generator=(Generator.Via_thunk.map[@modeportable])Generator.float~f:(funf()->of_float(f()));;let%templatequickcheck_observer=(Observer.Via_thunk.unmap[@modeportable])Observer.float~f:(funf()->to_float(f()));;letquickcheck_shrinker=Shrinker.atomicendmoduleStable=structmoduleV1=structtypenonrect=t[@@derivingglobalize]includeShared_derivedletstable_witness=Ppx_stable_witness_runtime.Stable_witness.assert_stableendendmoduleOption=structtypevalue=t[@@derivingcompare]moduleStable0=structmoduleV1=structmoduleF=Stable.V1include(F:sig@@portabletypenonrect=F.t[@@derivingbin_io~localize,hash,typerep,globalize,stable_witness]end)letcompare=[%eta2compare](* We use [compare.equal] here because, the float compare function have the behavior
that [compare nan nan = 0] (which is not the case for Float.equal). *)let%template[@modem=(global,local)][@inline][@zero_alloc]equal(t1@m)(t2@m)=[%compare.equal:value]t1t2;;letclamp_exn=letfloat_u_min=mininletfloat_u_max=maxinletfloat_u_clamp_exn=clamp_exninfunt~min~max->lethas_min=not(is_nanmin)inlethas_max=not(is_nanmax)inmatchhas_min,has_maxwith|false,false->t|true,false->float_u_maxtmin|false,true->float_u_mintmax|true,true->float_u_clamp_exnt~min~max;;endendincludeStable0.V1letnone=nanlet[@inline][@zero_alloc]is_none(t:t):bool=is_nantlet[@inline]unsafe_value(t:t):float#=tlet[@inline][@zero_alloc]is_somet=not(is_nonet)let[@inline][@zero_alloc]constt=of_floattlet[@inline][@zero_alloc]selectcondt1t2=selectcondt1t2let[@inline][@zero_alloc]unchecked_somev=vlet[@inline][@zero_alloc]some_ifbv=selectbvnonelet[@zero_alloc]somev=assert(is_somev);unchecked_somev;;letsome_is_representable=[%eta1is_some]letunchecked_value=[%eta1unsafe_value]let%template[@modem=(global,local)][@zero_alloc]of_option(opt@local)=matchoptwith|None->none|Somex->some(unboxx);;let%template[@modem=(global,local)][@zero_alloc]of_or_null(opt@local)=matchoptwith|Null->none|Thisx->some(unboxx);;let[@inline][@zero_alloc]first_somexy=first_non_nanxylet[@inline][@zero_alloc]some_orx~default=first_somex(unchecked_somedefault)moduleOptional_syntax=structtypenonrect=ttypevalue=float#moduleOptional_syntax=structlet[@zero_alloc]is_nonet=is_nonetlet[@zero_alloc]unsafe_valuet=unsafe_valuetendendmoduleO=structopenOlet(+)=[%eta2(+)]let(-)=[%eta2(-)]let(*)=[%eta2(*)]let(/)=[%eta2(/)]let(=)=[%eta2equal]let[@inline][@zero_alloc](<>)t1t2=not(equalt1t2)(* We need to check both operands, because: Float.nan ** 0. = 1.
1. ** Float.nan = 1. *)let[@zero_alloc](**)t1t2=ifBase.Bool.Non_short_circuiting.(is_nonet1||is_nonet2)thennoneelset1**t2;;letabst=abstletnegt=negtlet[@inline][@zero_alloc]mint1t2=mint1t2let[@inline][@zero_alloc]maxt1t2=maxt1t2endmoduleIeee_nan=struct(* These functions return false if either operand is [nan]. *)let(<)=[%eta2(<)]let(<=)=[%eta2(<=)]let(>)=[%eta2(>)]let(>=)=[%eta2(>=)]endincludeOletmergexy~f=letopenOptional_syntaxinmatch%optional_ux,ywith|None,None->none|Somex,None->x|None,Somey->y|Somex,Somey->fxy;;let%template[@modem=(global,local)]to_optiont=match%optional_u(t:t)with|None->None|Somef->letf=boxfinSomef[@exclave_if_localm];;let%template[@alloca=(heap,stack)]to_or_nullt=match%optional_u(t:t)with|None->Null|Somef->This(boxf)[@exclave_if_stacka];;moduleStable=structmoduleV1=structincludeStable0.V1let%template[@alloca@m=(heap_global,stack_local)]sexp_of_tt=(lett=(to_option[@modem])tin[%sexp(t:Base.Float.tBase.Option.t)][@alloca])[@exclave_if_stacka];;lett_of_sexpsexp=leto=[%of_sexp:Base.Float.tBase.Option.t]sexpinof_optiono;;endendincludeStable.V1let[@cold]raise__no_value(typea:float64)_:a=matchBase.raise_s[%message"None"]with|(_:Base.Nothing.t)->.;;letvalue_exnt=match%optional_u(t:t)with|None->raise__no_valuet|Somef->f;;letneg=[%eta1neg]letzero=zeroletone=onelet[@inline][@zero_allocstrict]of_float_nan_as_none(t:float#):t=tlet[@inline][@zero_alloc]to_float_none_as_nan(t:t):float#=tlet[@zero_alloc]scaletflt=O.(t*of_float_nan_as_noneflt)let[@zero_alloc]divtflt=O.(t/of_float_nan_as_noneflt)letis_finite=[%eta1is_finite]letis_inf=[%eta1is_inf]let[@inline][@zero_alloc]is_positivet=Ieee_nan.(t>zero)let[@inline][@zero_alloc]is_non_negativet=Ieee_nan.(t>=zero)let[@inline][@zero_alloc]is_negativet=Ieee_nan.(t<zero)let[@inline][@zero_alloc]is_non_positivet=Ieee_nan.(t<=zero)letis_integer=[%eta1is_integer]letto_stringt=Base.Sexp.to_string(sexp_of_tt)let[@zero_alloc]valuet~default=select(is_somet)(to_float_none_as_nant)defaultlet[@zero_alloc]divide_if_denominator_nonzero_else~(numerator:t)~(denominator:t)~(else_:t)=letis_denominator_nonzero=denominator<>zeroinselectis_denominator_nonzeroO.(numerator/denominator)else_;;includestructopenBase_quickcheckletquickcheck_generator=(Generator.Via_thunk.map[@modeportable])((Generator.option[@modeportable])Generator.float)~f:(funf()->of_option(f()));;letquickcheck_observer=(Observer.Via_thunk.unmap[@modeportable])((Observer.option[@modeportable])Observer.float)~f:(funf()->to_option(f()));;letquickcheck_shrinker=Shrinker.atomicendmoduleRef=structincludeReflet[@zero_alloc]create_localcontents=exclave_{contents}let[@inline]create_none()=createnonelet[@inline][@zero_alloc]set_nonet=settnonelet[@inline][@zero_alloc]set_float_nan_as_nonetflt=sett(of_float_nan_as_noneflt);;endend