123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144open!Importletinvalid_argf=Printf.invalid_argfletnegative_exponent()=Printf.invalid_argf"exponent can not be negative"()letoverflow()=Printf.invalid_argf"integer overflow in pow"()(* To implement [int64_pow], we use C code rather than OCaml to eliminate allocation. *)externalint_math_int_pow:int->int->int="Base_int_math_int_pow_stub"[@@noalloc]externalint_math_int64_pow:int64->int64->int64="Base_int_math_int64_pow_stub"letint_powbaseexponent=ifexponent<0thennegative_exponent();ifabs(base)>1&&(exponent>63||abs(base)>Pow_overflow_bounds.int_positive_overflow_bounds.(exponent))thenoverflow();int_math_int_powbaseexponent;;moduleInt64_with_comparisons=structincludeCaml.Int64external(<):int64->int64->bool="%lessthan"external(>):int64->int64->bool="%greaterthan"external(>=):int64->int64->bool="%greaterequal"end(* we don't do [abs] in int64 case to avoid allocation *)letint64_powbaseexponent=letopenInt64_with_comparisonsinifexponent<0Lthennegative_exponent();if(base>1L||base<(-1L))&&(exponent>63L||(base>=0L&&base>Pow_overflow_bounds.int64_positive_overflow_bounds.(to_intexponent))||(base<0L&&base<Pow_overflow_bounds.int64_negative_overflow_bounds.(to_intexponent)))thenoverflow();int_math_int64_powbaseexponent;;letint63_pow_on_int64baseexponent=letopenInt64_with_comparisonsinifexponent<0Lthennegative_exponent();ifabs(base)>1L&&(exponent>63L||abs(base)>Pow_overflow_bounds.int63_on_int64_positive_overflow_bounds.(to_intexponent))thenoverflow();int_math_int64_powbaseexponent;;moduletypeT=sigtypetincludeFloatable.Swithtypet:=tincludeStringable.Swithtypet:=tval(+):t->t->tval(-):t->t->tval(*):t->t->tval(/):t->t->tval(~-):t->tincludeComparisons.Infixwithtypet:=tvalabs:t->tvalneg:t->tvalzero:tvalof_int_exn:int->tvalrem:t->t->tendmoduleMake(X:T)=structopenXlet(%)xy=ify<=zerotheninvalid_argf"%s %% %s in core_int.ml: modulus should be positive"(to_stringx)(to_stringy)();letrval=X.remxyinifrval<zerothenrval+yelserval;;letone=of_int_exn1;;let(/%)xy=ify<=zerotheninvalid_argf"%s /%% %s in core_int.ml: divisor should be positive"(to_stringx)(to_stringy)();ifx<zerothen(x+one)/y-oneelsex/y;;(** float division of integers *)let(//)xy=to_floatx/.to_floaty;;letround_downi~to_multiple_of:modulus=i-(i%modulus);;letround_upi~to_multiple_of:modulus=letremainder=i%modulusinifremainder=zerothenielsei+modulus-remainder;;letround_towards_zeroi~to_multiple_of=ifi=zerothenzeroelseifi>zerothenround_downi~to_multiple_ofelseround_upi~to_multiple_of;;letround_nearesti~to_multiple_of:modulus=letremainder=i%modulusinifremainder*of_int_exn2<modulustheni-remainderelsei-remainder+modulus;;letround?(dir=`Nearest)i~to_multiple_of=matchdirwith|`Nearest->round_nearesti~to_multiple_of|`Down->round_downi~to_multiple_of|`Up->round_upi~to_multiple_of|`Zero->round_towards_zeroi~to_multiple_of;;end