123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258(* This file is free software, part of containers. See file "license" for more details. *)includeInttypet=inttype'aiter=('a->unit)->unitletzero=0letone=1letminus_one=-1letadd=(+)letsub=(-)letmul=(*)letdiv=(/)letsucc=succletpred=predletabs=absletmax_int=max_intletmin_int=min_intletequal(a:int)b=Stdlib.(=)abletcompare(a:int)b=compareab(* use FNV:
https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function *)lethash(n:int):int=letoffset_basis=0xcbf29ce484222325Linletprime=0x100000001b3Linleth=refoffset_basisinfork=0to7do(h:=Int64.(mul!hprime));(* h := h xor (k-th byte of n) *)h:=Int64.(logxor!h(of_int((nlsr(k*8))land0xff)))done;(* truncate back to int and remove sign *)Int64.to_int!hlandmax_intletrangeijyield=letrecupijyield=ifi=jthenyieldielse(yieldi;up(i+1)jyield)anddownijyield=ifi=jthenyieldielse(yieldi;down(i-1)jyield)inifi<=jthenupijyieldelsedownijyieldletrange'ijyield=ifi<jthenrangei(j-1)yieldelseifi=jthen()elserangei(j+1)yieldletsigni=comparei0letnegi=-iletpowab=letrecauxacc=function|1->acc|n->ifnmod2=0thenaux(acc*acc)(n/2)elseacc*aux(acc*acc)(n/2)inmatchbwith|0->ifa=0thenraise(Invalid_argument"pow: undefined value 0^0")else1|bwhenb<0->raise(Invalid_argument"pow: can't raise int to negative power")|b->auxabmoduleInfix:sigval(=):t->t->boolval(<>):t->t->boolval(<):t->t->boolval(>):t->t->boolval(<=):t->t->boolval(>=):t->t->boolval(--):t->t->titerval(--^):t->t->titerval(+):t->t->tval(-):t->t->tval(~-):t->tval(*):t->t->tval(/):t->t->tval(**):t->t->tval(mod):t->t->tval(land):t->t->tval(lor):t->t->tval(lxor):t->t->tvallnot:t->tval(lsl):t->int->tval(lsr):t->int->tval(asr):t->int->tend=structincludeStdliblet(--)=rangelet(--^)=range'let(**)=powendincludeInfixletmin:t->t->t=Stdlib.minletmax:t->t->t=Stdlib.maxletfloor_divan=ifa<0&&n>=0then((a+1)/n)-1elseifa>0&&n<0then((a-1)/n)-1elsea/nletbool_neq(a:bool)b=Stdlib.(<>)abletreman=lety=amodninifbool_neq(y<0)(n<0)&&y<>0theny+nelseytype'aprinter=Format.formatter->'a->unittype'arandom_gen=Random.State.t->'aletrandomnst=Random.State.intstnletrandom_small=random100letrandom_rangeijst=i+random(j-i)stletppfmt=Format.pp_print_intfmtletmost_significant_bit=-1lxor(-1lsr1)letto_string=string_of_intletof_strings=trySome(int_of_strings)withFailure_->Noneletof_string_exn=Stdlib.int_of_stringletto_float=float_of_intletof_float=int_of_floattypeoutput=char->unit(* abstract printer *)letto_binary_gen(out:output)n=letn=ifn<0then(out'-';-n)elseninout'0';out'b';letrecloopstartedbitn=ifbit=0then(ifnotstartedthenout'0')else(letb=nlandbitinifb=0then(ifstartedthenout'0';loopstarted(bitlsr1)n)else(out'1';looptrue(bitlsr1)n))inloopfalsemost_significant_bitnletpp_binaryoutn=to_binary_gen(Format.pp_print_charout)nletto_string_binaryn=letbuf=Buffer.create16into_binary_gen(Buffer.add_charbuf)n;Buffer.contentsbufletrange_by~stepijyield=letrecrangeijyield=ifi=jthenyieldielse(yieldi;range(i+step)jyield)inifstep=0thenraise(Invalid_argument"CCInt.range_by")elseififstep>0theni>jelsei<jthen()elserangei(((j-i)/step*step)+i)yield(*
from https://en.wikipedia.org/wiki/Hamming_weight
//This uses fewer arithmetic operations than any other known
//implementation on machines with slow multiplication.
//It uses 17 arithmetic operations.
int popcount_2(uint64_t x) {
x -= (x >> 1) & m1; //put count of each 2 bits into those 2 bits
x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits
x = (x + (x >> 4)) & m4; //put count of each 8 bits into those 8 bits
x += x >> 8; //put count of each 16 bits into their lowest 8 bits
x += x >> 16; //put count of each 32 bits into their lowest 8 bits
x += x >> 32; //put count of each 64 bits into their lowest 8 bits
return x & 0x7f;
}
m1 = 0x5555555555555555
m2 = 0x3333333333333333
m4 = 0x0f0f0f0f0f0f0f0f
*)letpopcount(b:int):int=letm1=0x5555555555555555Linletm2=0x3333333333333333Linletm4=0x0f0f0f0f0f0f0f0fLinletopenInt64inletb=of_intbin(* int->int64 *)letb=logandb0x7fffffffffffffffLin(* remove sign bit, we deal with uint64 here *)letb=subb(logand(shift_right_logicalb1)m1)inletb=add(logandbm2)(logand(shift_right_logicalb2)m2)inletb=logand(addb(shift_right_logicalb4))m4inletb=addb(shift_right_logicalb8)inletb=addb(shift_right_logicalb16)inletb=addb(shift_right_logicalb32)inletb=logandb0x7fLinto_intbletlogand=(land)letlogor=(lor)letlogxor=(lxor)letlognot=lnotletshift_left=(lsl)letshift_right=(asr)letshift_right_logical=(lsr)