123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730open!BasemoduleI=Base.Int64typet=int64#moduleBoxed=Base.Int64let[@inline]globalize(local_(t:t))=texternalof_int64:(int64[@local_opt])->t@@portable="%unbox_int64"externalto_int64:t->(int64[@local_opt])@@portable="%box_int64"externalbox_float:float#->(float[@local_opt])@@portable="%box_float"externalunbox_float:(float[@local_opt])->float#@@portable="%unbox_float"(* Note about the implementation strategy:
Most functions in this file are implemented by boxing the int, calling the equivalent
function on boxed ints, 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.
*)let[@inline]selectbt1t2=of_int64(Ocaml_intrinsics_kernel.Conditional.select_int64b(to_int64t1)(to_int64t2));;let[@inline]to_intx=(I.to_int[@inlinedhint])(to_int64x)let[@inline]of_floatx=of_int64((I.of_float[@inlinedhint])(box_floatx))let[@inline]to_floatt=(I.to_float[@inlinedhint])(to_int64t)|>unbox_floatlet[@inline]of_int_exnx=of_int64((I.of_int_exn[@inlinedhint])x)moduleShared_derived=structlet[@inline]t_of_sexpx=of_int64((I.t_of_sexp[@inlinedhint])x)let%template[@alloca=(heap,stack)][@inline]sexp_of_tt=(I.sexp_of_t[@alloca][@inlinedhint])(to_int64t)[@exclave_if_stacka];;lett_sexp_grammar=Sexplib0.Sexp_grammar.coerceI.t_sexp_grammarletbin_shape_t=Bin_prot_unboxed_numbers.Int64_u.bin_shape_t[%%template[@@@mode.defaultm=(global,local)]let[@inlinealways]bin_size_tt=(Bin_prot_unboxed_numbers.Int64_u.bin_size_t[@modem][@inlined])t;;let[@inlinealways]bin_write_tbuf~post=(Bin_prot_unboxed_numbers.Int64_u.bin_write_t[@modem][@inlined])buf~post;;]let[@inlinealways]bin_read_tbuf~pos_ref=(Bin_prot_unboxed_numbers.Int64_u.bin_read_t[@inlined])buf~pos_ref;;let__bin_read_t__=Bin_prot_unboxed_numbers.Int64_u.__bin_read_t__letbin_writer_t=Bin_prot_unboxed_numbers.Int64_u.bin_writer_tletbin_reader_t=Bin_prot_unboxed_numbers.Int64_u.bin_reader_tletbin_t=Bin_prot_unboxed_numbers.Int64_u.bin_tlet[@inline]hash_fold_tstatet=(I.hash_fold_t[@inlinedhint])state(to_int64t)let[@inline]hasht=(I.hash[@inlinedhint])(to_int64t)lettyperep_of_t=Typerep_lib.Std.Typerep.Int64_ulet[@inline]of_stringx=of_int64((I.of_string[@inlinedhint])x)let%template[@modem=(global,local)][@inline][@zero_alloc]equalt1t2:bool=(I.equal[@modem])(to_int64t1)(to_int64t2);;let%template[@modem=(global,local)][@inline][@zero_alloc]comparet1t2:int=(I.compare[@modem])(to_int64t1)(to_int64t2);;endincludeShared_derivedmoduleO=structletzero=of_int64I.O.zerolet[@inline](+)t1t2=of_int64(I.O.(+)(to_int64t1)(to_int64t2))let[@inline](-)t1t2=of_int64(I.O.(-)(to_int64t1)(to_int64t2))let[@inline](*)t1t2=of_int64(I.O.(*)(to_int64t1)(to_int64t2))let[@inline](**)t1t2=of_int64((I.O.(**)[@inlinedhint])(to_int64t1)(to_int64t2));;let[@inline](>=)t1t2=I.O.(>=)(to_int64t1)(to_int64t2)let[@inline](<=)t1t2=I.O.(<=)(to_int64t1)(to_int64t2)let[@inline](=)t1t2=I.O.(=)(to_int64t1)(to_int64t2)let[@inline](>)t1t2=I.O.(>)(to_int64t1)(to_int64t2)let[@inline](<)t1t2=I.O.(<)(to_int64t1)(to_int64t2)let[@inline](<>)t1t2=I.O.(<>)(to_int64t1)(to_int64t2)let[@inline]negt=of_int64(I.O.neg(to_int64t))let[@inline](~-)t=of_int64(I.O.(~-)(to_int64t))let[@inline](/%)t1t2=of_int64((I.O.(/%)[@inlinedhint])(to_int64t1)(to_int64t2));;let[@inline](%)t1t2=of_int64((I.O.(%)[@inlinedhint])(to_int64t1)(to_int64t2));;let[@inline](/)t1t2=of_int64(I.O.(/)(to_int64t1)(to_int64t2))let[@inline](//)t1t2=(I.O.(//)[@inlinedhint])(to_int64t1)(to_int64t2)|>unbox_float;;let[@inline](land)t1t2=of_int64(I.O.(land)(to_int64t1)(to_int64t2))let[@inline](lor)t1t2=of_int64(I.O.(lor)(to_int64t1)(to_int64t2))let[@inline](lxor)t1t2=of_int64(I.O.(lxor)(to_int64t1)(to_int64t2))let[@inline]lnott=of_int64((I.O.lnot[@inlinedhint])(to_int64t))let[@inline](lsl)tx=of_int64(I.O.(lsl)(to_int64t)x)let[@inline](asr)tx=of_int64(I.O.(asr)(to_int64t)x)let[@inline]abst=of_int64((I.O.abs[@inlinedhint])(to_int64t))let[@inline](lsr)tx=of_int64((I.O.((lsr))[@inlinedhint])(to_int64t)x)externalbox:int64#->(int64[@local_opt])@@portable="%box_int64"externalunbox:(int64[@local_opt])->int64#@@portable="%unbox_int64"endincludeO(* [min] can't be implemented in terms of [Int64.min] because that function uses
[caml_csel_value] which forces the integers to be boxed leading to unwanted
allocations. Instead, we have to copy the function definition and use a different
[select] function that knows how to handle unboxed types. *)let[@inline]mint1t2:t=select(t1<=t2)t1t2(* Can't be implemented using [Int64.max] for the same reason as [min] *)let[@inline]maxt1t2:t=select(t1>=t2)t1t2let[@inline]ascendingt1t2:int=(I.ascending[@inlinedhint])(to_int64t1)(to_int64t2);;let[@inline]descendingt1t2:int=(I.descending[@inlinedhint])(to_int64t1)(to_int64t2);;let[@inline]betweent~low~high:bool=(I.between[@inlinedhint])(to_int64t)~low:(to_int64low)~high:(to_int64high);;let[@inline]clamp_uncheckedt~min:min_~max:max_=(min[@inlinedhint])tmax_|>(max[@inlinedhint])min_;;(* Can't be implemented using [Int64.clamp_exn] for the same reason as [min] *)let[@inline]clamp_exnt~min~max=assert(min<=max);(clamp_unchecked[@inlinedhint])t~min~max;;let[@inline]ppppft:unit=(I.pp[@inlinedhint])ppf(to_int64t)let[@inline]invariantt:unit=(I.invariant[@inlinedhint])(to_int64t)let[@inline]is_positivet=(I.is_positive[@inlinedhint])(to_int64t)let[@inline]is_non_negativet=(I.is_non_negative[@inlinedhint])(to_int64t)let[@inline]is_negativet=(I.is_negative[@inlinedhint])(to_int64t)let[@inline]is_non_positivet=(I.is_non_positive[@inlinedhint])(to_int64t)let[@inline]signt=(I.sign[@inlinedhint])(to_int64t)let[@inline]to_string_hum?delimitert=(I.to_string_hum[@inlinedhint])?delimiter(to_int64t);;letzero=of_int64I.zeroletone=of_int64I.oneletminus_one=of_int64I.minus_onelet[@inline]remt1t2=of_int64((I.rem[@inlinedhint])(to_int64t1)(to_int64t2))let[@inline]round?dirt~to_multiple_of:t2=of_int64((I.round[@inlinedhint])?dir(to_int64t)~to_multiple_of:(to_int64t2));;(* let[@inline] round_towards_zero t ~to_multiple_of:t2 =
* of_int64
* ((I.round_towards_zero [@inlined hint]) (to_int64 t) ~to_multiple_of:(to_int64 t2))
* ;; *)let[@inline]round_downt~to_multiple_of:t2=of_int64((I.round_down[@inlinedhint])(to_int64t)~to_multiple_of:(to_int64t2));;let[@inline]round_upt~to_multiple_of:t2=of_int64((I.round_up[@inlinedhint])(to_int64t)~to_multiple_of:(to_int64t2));;let[@inline]round_nearestt~to_multiple_of:t2=of_int64((I.round_nearest[@inlinedhint])(to_int64t)~to_multiple_of:(to_int64t2));;let[@inline]abst=of_int64((I.abs[@inlinedhint])(to_int64t))let[@inline]succt=of_int64((I.succ[@inlinedhint])(to_int64t))let[@inline]predt=of_int64((I.pred[@inlinedhint])(to_int64t))let[@inline]powt1t2=of_int64((I.pow[@inlinedhint])(to_int64t1)(to_int64t2))let[@inline]bit_andt1t2=of_int64((I.bit_and[@inlinedhint])(to_int64t1)(to_int64t2));;let[@inline]bit_ort1t2=of_int64((I.bit_or[@inlinedhint])(to_int64t1)(to_int64t2));;let[@inline]bit_xort1t2=of_int64((I.bit_xor[@inlinedhint])(to_int64t1)(to_int64t2));;let[@inline]bit_nott=of_int64((I.bit_not[@inlinedhint])(to_int64t))let[@inline]popcountt=of_int64((I.popcount[@inlinedhint])(to_int64t))let[@inline]shift_lefttx=of_int64((I.shift_left[@inlinedhint])(to_int64t)x)let[@inline]shift_righttx=of_int64((I.shift_right[@inlinedhint])(to_int64t)x)let[@inline]of_int32_exnx=of_int64(I.of_int32_exnx)let[@inline]to_int32_exnt=(I.to_int32_exn[@inlinedhint])(to_int64t)let[@inline]of_int64_exnt=of_int64tlet[@inline]of_nativeint_exnx=of_int64((I.of_nativeint_exn[@inlinedhint])x)let[@inline]to_nativeint_exnt=(I.to_nativeint_exn[@inlinedhint])(to_int64t)let[@inline]of_float_uncheckedf=of_int64((I.of_float_unchecked[@inlinedhint])(box_floatf));;letnum_bits=I.num_bitsletmax_value=of_int64I.max_valueletmin_value=of_int64I.min_valuelet[@inline](lsr)tx=of_int64((I.((lsr))[@inlinedhint])(to_int64t)x)let[@inline]shift_right_logicalti=tlsrilet[@inline]ceil_pow2t=of_int64((I.ceil_pow2[@inlinedhint])(to_int64t))let[@inline]floor_pow2t=of_int64((I.floor_pow2[@inlinedhint])(to_int64t))let[@inline]ceil_log2t=(I.ceil_log2[@inlinedhint])(to_int64t)|>of_int64let[@inline]floor_log2t=(I.floor_log2[@inlinedhint])(to_int64t)|>of_int64let[@inline]is_pow2t=(I.is_pow2[@inlinedhint])(to_int64t)let[@inline]clzt=(I.clz[@inlinedhint])(to_int64t)|>of_int64let[@inline]ctzt=(I.ctz[@inlinedhint])(to_int64t)|>of_int64let[@inline]to_nativeintt=(I.to_nativeint[@inlinedhint])(to_int64t)let[@inline]of_intx=of_int64(I.of_intx)let[@inline]of_int32x=of_int64(I.of_int32x)let[@inline]to_int32t=(I.to_int32[@inlinedhint])(to_int64t)let[@inline]to_int32_trunct=I.to_int32_trunc(to_int64t)let[@inline]to_nativeint_trunct=I.to_nativeint_trunc(to_int64t)let[@inline]to_int_trunct=I.to_int_trunc(to_int64t)let[@inline]of_nativeintx=of_int64(I.of_nativeintx)let[@inline]of_boolx=of_int(Bool.to_intx)let[@inline]bits_of_floatf=of_int64(I.bits_of_float(box_floatf))let[@inline]float_of_bitst=I.float_of_bits(to_int64t)|>unbox_floatlet[@inline]bswap16t=of_int64((I.bswap16[@inlinedhint])(to_int64t))let[@inline]bswap32t=of_int64((I.bswap32[@inlinedhint])(to_int64t))let[@inline]bswap48t=of_int64((I.bswap48[@inlinedhint])(to_int64t))let[@inline]bswap64t=of_int64(I.bswap64(to_int64t))(* Inlined from [Base.Int_conversions], and modified to operate over unboxed things. *)let[@cold]to_int_exn_failurex=Base.Printf.failwithf"conversion from int64 to int failed: %s is out of range"(I.to_string(to_int64x))();;let[@inline]to_int_exnt=letr=to_int_trunctinift<>of_intrthento_int_exn_failuret;r;;(* From https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel *)let[@inline][@zero_alloc]rev_bitst=let[@inline]swapt~shift~mask=lethi=maskland(tlsrshift)inletlo=(masklandt)lslshiftinhilorloint|>swap~shift:1~mask:#0x5555555555555555L|>swap~shift:2~mask:#0x3333333333333333L|>swap~shift:4~mask:#0x0F0F0F0F0F0F0F0FL|>bswap64;;moduleArray_index=structexternalget:('a:anymodseparable).('aarray[@local_opt])->(t[@local_opt])->'a@@portable="%array_safe_get_indexed_by_int64#"[@@layout_poly]externalset:('a:anymodseparable).('aarray[@local_opt])->(t[@local_opt])->'a->unit@@portable="%array_safe_set_indexed_by_int64#"[@@layout_poly]externalunsafe_get:('a:anymodseparable).('aarray[@local_opt])->(t[@local_opt])->'a@@portable="%array_unsafe_get_indexed_by_int64#"[@@layout_poly]externalunsafe_set:('a:anymodseparable).('aarray[@local_opt])->(t[@local_opt])->'a->unit@@portable="%array_unsafe_set_indexed_by_int64#"[@@layout_poly]endmoduleIarray_index=structexternalget:('a:anymodseparable).('aiarray[@local_opt])->(t[@local_opt])->'a@@portable="%array_safe_get_indexed_by_int64#"[@@layout_poly]externalunsafe_get:('a:anymodseparable).('aiarray[@local_opt])->(t[@local_opt])->'a@@portable="%array_unsafe_get_indexed_by_int64#"[@@layout_poly]endmoduleArray=structtype('a:bits64)t='aarrayexternallength:('at[@local_opt])->int@@portable="%array_length"externalget:('at[@local_opt])->int->'a@@portable="%array_safe_get"externalset:('at[@local_opt])->int->'a->unit@@portable="%array_safe_set"externalunsafe_get:('at[@local_opt])->int->'a@@portable="%array_unsafe_get"externalunsafe_set:('at[@local_opt])->int->'a->unit@@portable="%array_unsafe_set"externalcreate_uninitialized:len:int->int64#t@@portable="caml_make_unboxed_int64_vect_bytecode""caml_make_unboxed_int64_vect"externalunsafe_create_uninitialized:len:int->('a:bits64)t@@portable="caml_make_unboxed_int64_vect_bytecode""caml_make_unboxed_int64_vect"externalunsafe_blit:src:('at[@local_opt])->src_pos:int->dst:('at[@local_opt])->dst_pos:int->len:int->unit@@portable="caml_array_blit""caml_unboxed_int64_vect_blit"letsexp_of_tsexp_of__aar=letopenBaseinletlst_ref=ref[]infori=lengthar-1downto0dolst_ref:=sexp_of__a(getari)::!lst_refdone;Sexp.List!lst_ref;;letmap(type(a:bits64)(b:bits64))(t:at)~(f:a->b):bt=letlen=lengthtinletr=unsafe_create_uninitialized~leninfori=0toBase.Int.O.(len-1)doletx=unsafe_gettiinlety=fxinunsafe_setriydone;r;;letinitlen~f=letr=unsafe_create_uninitialized~leninfori=0toBase.Int.O.(len-1)dounsafe_setri(fi)done;r;;letequalequal_a(local_s)(local_t)=letl=lengthsinInt.equall(lengtht)&&letrecloopi=matchBase.Int.is_negativeiwith|true->true|false->equal_a(unsafe_getsi)(unsafe_getti)&&loopBase.Int.O.(i-1)inloopBase.Int.O.(l-1)[@nontail];;letcopyt=init(lengtht)~f:(funi->unsafe_getti)[@nontail]endlet%template[@alloca=(heap,stack)]to_stringn=(Base.Exported_for_specific_uses.Integer_to_string.int64_u_to_string[@alloca])n[@exclave_if_stacka];;moduleStable=structmoduleV1=structtypenonrect=t[@@derivingglobalize]includeShared_derivedletto_string=to_stringletstable_witness=Ppx_stable_witness_runtime.Stable_witness.assert_stableendendmoduleRef=structtypenonrec('elt:bits64)t={mutablecontents:'elt}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][@zero_alloc]incrt=addt#1Llet[@inline][@zero_alloc]decrt=addt(-#1L)moduleO=structletref=create_locallet[@inline][@zero_alloc](!)t=gettlet[@inline][@zero_alloc](:=)tx=settxlet[@inline][@zero_alloc](+=)tx=addtxlet[@inline][@zero_alloc](|=)tx:unit=sett(gettlorx)let[@inline][@zero_alloc]incrt:unit=incrtlet[@inline][@zero_alloc]decrt:unit=decrtendendlet[@inline]for_loop_known_to_run_at_least_once~start_incl~end_excl~(local_f)=letrecloopi=exclave_(f[@inlinedhint])i;leti=i+#1Lin(* important: <>, NOT <. In particular, for inclusive for, [end_excl] might wrap (and
in fact be less than all i.) The point is that [end_excl] is the exact number we
don't want to loop on. *)ifi<>end_exclthenloopiinloopstart_incl[@nontail];;let[@inline]for_loop~start_incl~end_excl~(local_f)=ifstart_incl<end_exclthenfor_loop_known_to_run_at_least_once~start_incl~end_excl~f;;let[@inline]for_loop_incl~start_incl~end_incl~(local_f)=ifstart_incl<=end_inclthen(letend_excl=end_incl+#1Linfor_loop_known_to_run_at_least_once~start_incl~end_excl~f);;let[@inline]rangen~(local_f)=for_loop~start_incl:#0L~end_excl:n~flet[@inline]recrange_rev_loopn~f=letn=n-#1Lin(f[@inlinedhint])n;ifn>#0Lthenrange_rev_loopn~f;;let[@inline]range_revn~f=ifn>#0Lthenrange_rev_loopn~fincludestructopenBase_quickchecklet%templatequickcheck_generator=(Generator.Via_thunk.map[@modeportable])Generator.int64~f:(funf()->of_int64(f()));;let%templatequickcheck_observer=(Observer.Via_thunk.unmap[@modeportable])Observer.int64~f:(funf()->to_int64(f()));;letquickcheck_shrinker=Shrinker.atomicendmoduleHex_unsigned=structmoduleBool=Base.BoolmoduleBytes=Base.BytesmoduleChar=Base.CharmoduleInt=Base.IntmoduleNothing=Base.NothingmoduleSexp=Base.SexpmoduleString=Base.StringmoduleTo_string_config=structmoduleCase=structtypet=|Lowercase|Uppercase[@@derivingequal~localize,sexp_of]endtypet={prefix_with_0x:bool;render_letters:Case.t}[@@derivingbox,equal~localize,sexp_of]letdefault={prefix_with_0x=true;render_letters=Lowercase}let[@inline]starting_offsett=of_int(Bool.to_intt.#prefix_with_0x)*#2Llet[@inline]ascii_at=leta=matcht.#render_letterswith|Lowercase->'a'|Uppercase->'A'inof_int(Char.to_inta);;endmodulePrivate=structtypedigits_to_process=tlet[@inline]ceil_divab=letopenOin(a+(b-#1L))/b;;(* [max 1] because there is always at least one digit printed, even if the input is 0. *)let[@inline]digits_to_processt~max_digits=letopenOinclamp_unchecked~min:#1L~max:max_digits(ceil_div(#64L-clzt)#4L);;(* 2 bytes for the "0x" prefix. plus one byte per 4-bit digit. *)let[@inline]to_string_required_length~config~digits_to_process=letopenOinto_int_trunc(To_string_config.starting_offsetconfig+digits_to_process);;let[@inlinenever]to_string_intotout~(config:To_string_config.t#)~digits_to_process=letopenOinletset=Bytes.unsafe_setinifconfig.#prefix_with_0xthen(setout0'0';setout1'x');letstarting_offset=To_string_config.starting_offsetconfiginletascii_a=To_string_config.ascii_aconfiginrange_revdigits_to_process~f:(funi->letdigit=(tlsrto_int_trunc(i*#4L))land#0xFLinletoutput_index=starting_offset+digits_to_process-i-#1Linletascii_zero=of_int(Char.to_int'0')inletchar_as_int=select(digit>=#10L)(digit+ascii_a-#10L)(digit+ascii_zero)insetout(to_int_truncoutput_index)(Char.unsafe_of_int(to_int_truncchar_as_int)))[@nontail];;let[@cold]malformed_hex_strings=matchBase.raise_s[%message"malformed unsigned hex string"~_:([%globalize:String.t]s:String.t)]with|(_:Nothing.t)->.;;let[@inlinenever]of_string(s:string@local)~max_digits=letopenOinletopenRef.Oinletget=String.unsafe_getinletlength=String.lengthsinifInt.O.(length<3)||Char.(<>)(gets0)'0'||Char.(<>)(gets1)'x'thenmalformed_hex_strings;letr=Ref.create_local#0Lin(* [valid] would be better off as a bool ref (where 1=true and 0=false), but it's
annoying to work with bits64 and value refs in the same scope. *)letvalid=Ref.create_local#1Linletnum_digits=of_intlength-#2Linrangenum_digits~f:(funi->letindex=i+#2Linletchar=gets(to_int_truncindex)inletint=of_int(Char.to_intchar)inletascii_lowercase_a=of_int(Char.to_int'a')inletascii_uppercase_a=of_int(Char.to_int'A')inletascii_zero=of_int(Char.to_int'0')inletopenBool.Non_short_circuitinginletlowercase_ascii=int>=ascii_lowercase_a&&int<ascii_lowercase_a+#6Linletuppercase_ascii=int>=ascii_uppercase_a&&int<ascii_uppercase_a+#6Linletdecimal_digit=int>=ascii_zero&&int<ascii_zero+#10Linletdigit_valid=lowercase_ascii||uppercase_ascii||decimal_digitinletdigit=int-ascii_zero|>selectlowercase_ascii(int-ascii_lowercase_a+#10L)|>selectuppercase_ascii(int-ascii_uppercase_a+#10L)inletoutput_bit_offset=(num_digits-#1L-i)*#4Linr:=!rlor(digitlslto_int_truncoutput_bit_offset);valid:=!validlandof_booldigit_valid);letmalformed=!valid=#0Llorof_bool(num_digits>max_digits)inifmalformedthenmalformed_hex_strings;!r[@nontail];;let[@cold]t_of_sexp_failedsexp=Base.raise_s[%message"expected Atom, got List"~_:([%globalize:Sexp.t]sexp:Sexp.t)];;let[@inline]t_of_sexp(sexp:Sexp.t@local)~max_digits=matchsexpwith|Atoms->of_strings~max_digits|List_->(matcht_of_sexp_failedsexpwith|(_:Nothing.t)->.);;endlet[@inline]max_digits()=#16LmoduleLocal=structtypenonrect=tletcompare=Shared_derived.comparelethash=Shared_derived.hashlethash_fold_t=Shared_derived.hash_fold_tlet[@inline]of_strings=Private.of_strings~max_digits:(max_digits())let[@inline]t_of_sexpsexp=Private.t_of_sexpsexp~max_digits:(max_digits())let[@inlinenever]to_string_customt~config=exclave_letdigits_to_process=Private.digits_to_processt~max_digits:#16Linletbytes=Bytes.create_local(Private.to_string_required_length~config~digits_to_process)inPrivate.to_string_intotbytes~config~digits_to_process;Bytes.unsafe_to_string~no_mutation_while_string_reachable:bytes;;let[@inline]to_stringt=exclave_to_string_customt~config:To_string_config.(unboxdefault);;let[@inline]sexp_of_tt:Sexp.t=exclave_Atom(to_stringt)endtypenonrect=tletcompare=Local.comparelethash=Shared_derived.hashlethash_fold_t=Shared_derived.hash_fold_tlet[@inline]of_strings=Private.of_strings~max_digits:(max_digits())let[@inline]t_of_sexpsexp=Private.t_of_sexpsexp~max_digits:(max_digits())let[@inlinenever]to_string_customt~config=letdigits_to_process=Private.digits_to_processt~max_digits:#16Linletbytes=Bytes.create(Private.to_string_required_length~config~digits_to_process)inPrivate.to_string_intotbytes~config~digits_to_process;Bytes.unsafe_to_string~no_mutation_while_string_reachable:bytes[@nontail];;let[@inline]to_stringt:string=to_string_customt~config:To_string_config.(unboxdefault);;let[@inline]sexp_of_tt:Sexp.t=Atom(to_stringt)endmoduleOption=structtypenonrect=ttypevalue=tletnone=min_valuelet[@inline]is_nonet=t=nonelet[@inline]is_somet=not(is_nonet)let[@inline]somet=assert(is_somet);t;;let[@inline]unchecked_somet=tlet[@inline]some_is_representablet=is_sometlet[@inline]valuet~default=select(is_somet)tdefaultlet[@inline]unchecked_valuet=tlet[@inline]to_optiont=ifis_sometthenSome(boxt)elseNonelet[@inline]of_optiont=matchtwith|None->none|Somet->some(unboxt);;let[@inline]to_local_optiont=exclave_ifis_sometthenSome(boxt)elseNonelet[@inline]of_local_optiont=of_optiontmoduleOptional_syntax=structmoduleOptional_syntax=structlet[@inline]is_nonet=is_nonetlet[@inline]unsafe_valuet=unchecked_valuetendendend