123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209(*
* BatRandom - Additional randomization operations
* Copyright (C) 1996 Damien Doligez
* 2009 David Teller, LIFO, Universite d'Orleans
* 2009 Pierre Chambart
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version,
* with the special exception on linking described in file LICENSE.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)exceptionEmptyletinit=Random.initletfull_init=Random.full_initletself_init=Random.self_initletbits=Random.bitsletint=Random.int##V>=4.13##letfull_int=Random.full_int##V>=5.2##letint_in_range=Random.int_in_rangeletint32=Random.int32##V>=5.2##letint32_in_range=Random.int32_in_rangeletint64=Random.int64##V>=5.2##letint64_in_range=Random.int64_in_rangeletnativeint=Random.nativeint##V>=5.2##letnativeint_in_range=Random.nativeint_in_rangeletfloat=Random.floatletbool=Random.boolletchar()=Char.chr(int256)##V>=4.14##letbits32=Random.bits32##V>=4.14##letbits64=Random.bits64##V>=4.14##letnativebits=Random.nativebits##V>=5##letsplit=Random.splitletfull_range_int=ifSys.word_size=32then(* need 31-bits of entropy, bits() gives 30 *)fun()->ifbool()then-(bits ())-1elsebits()else(* 64-bit words *)fun()->(* need 63 bits of entropy , bits + bits + bits land 0b11 *)letb=(bits())lor(bits()lsl30)lor((bits()land0b11)lsl60)inifbool()thenbelse-b-1moduleState =structincludeRandom.Stateletchart=Char.chr(intt256)(**A constructor for enumerations of random numbers. *)letenum_bitsstate()=BatEnum.from(fun()->bitsstate)letenum_int state bound =BatEnum.from(fun()->intstatebound)letenum_int32statebound=BatEnum.from (fun()->int32statebound)letenum_int64statebound=BatEnum.from(fun()->int64statebound)letenum_floatstatebound =BatEnum.from(fun()->floatstatebound)letenum_nativeintstatebound=BatEnum.from(fun()->nativeintstatebound)letenum_boolstate()=BatEnum.from(fun()->boolstate)letenum_charstate()=BatEnum.from (fun()->charstate)##V>=5##externalnext:t->(int64[@unboxed])##V>=5## ="caml_lxm_next""caml_lxm_next_unboxed"[@@noalloc]endletenum_bits()=BatEnum.frombitsletenum_intbound=BatEnum.from(fun()->intbound)letenum_int32bound=BatEnum.from(fun()-> int32bound)letenum_int64bound=BatEnum.from(fun()->int64bound)letenum_floatbound=BatEnum.from(fun()->floatbound)letenum_nativeintbound=BatEnum.from(fun()->nativeintbound)letenum_bool()=BatEnum.fromboolletenum_char()=BatEnum.fromcharletchoicee=ifBatEnum.is_emptyethenraiseEmptyelse(BatEnum.drop(int(BatEnum.counte))e;BatEnum.get_exne)(* Reservoir sampling algorithm (see for instance
http://en.wikipedia.org/wiki/Reservoir_sampling)
TODO: a more efficient algorithm when given enum length is known *)letmulti_choicene=ifBatEnum.is_emptyethenBatEnum.empty()elseletnexte=BatOption.get(BatEnum.gete)in(* Note: this assumes that Array.init will call the function for i = 0 to n-1in that order *)letchosen=Array.initn(funi->nexte,i)inBatEnum.iteri(funix->leti=i+n+1in(* we've already chosen the n first items *)letr=Random.intiinifr<nthenchosen.(r)<-x,i)e;Array.sort(fun(_,i1)(_,i2)->comparei1i2)chosen;BatArray.enum(Array.mapfstchosen)(*$T multi_choice
BatEnum.is_empty (multi_choice 0 (BatEnum.empty ()))
BatEnum.count (multi_choice 3 (BatList.enum [1;2;3;4;5])) = 3
let l = [1;2;3;4;5] in let e = multi_choice 2 (BatList.enum l) in \
let a = BatOption.get (BatEnum.get e) in a < BatOption.get (BatEnum.get e)
let x = BatEnum.repeat ~times:99 [0;1]/@ (fun l-> \
multi_choice 1 (BatList.enum l)) /@ \
BatEnum.get_exn |> \
reduce (+) in x > 0 && x < 99
*)(* Note: this last test check that the first nor the last item is always chosen *)letshufflee=leta=BatArray.of_enumeinBatInnerShuffle.array_shufflea;aletget_state=Random.get_stateletset_state=Random.set_statemoduleIncubator=structmodulePrivate_state_enums=structmoduleState=structincludeState (* the state we defined up above *)letrandom_enum state next =letrecauxstate=letnext()=nextstateinletcount ()=raiseBatEnum.Infinite_enuminletclone()=aux(copystate)inBatEnum.make~next~count~cloneinaux(copystate)letenum_bitsstate()=random_enumstatebitsletenum_intstatebound=random_enumstate(funstate->intstatebound)letenum_int32statebound=random_enum state(funstate->int32statebound)letenum_int64statebound=random_enumstate(funstate->int64statebound)let enum_floatstatebound=random_enumstate(funstate ->floatstatebound)letenum_nativeintstatebound=random_enum state(funstate->nativeintstatebound)letenum_boolstate()=random_enumstateboolletenum_charstate()=random_enumstatechar##V<5##typeimplementation ={st:intarray;mutable idx:int}##V>=5##openBigarray##V>=5##typeimplementation=(int64,int64_elt,c_layout)Array1.t(* external t_of_impl: implementation -> t = "%identity" *)externalimpl_of_t:t->implementation="%identity"letperturbstate=##V<5##letimpl=impl_of_tstatein##V<5##make(Array.appendimpl.st[|impl.idx|])##V>=5## let_=State.next statein##V>=5##stateend(* bumps the existing global RNG state (reseeding on its current
array) and returns the previous state *)letperturb_global()=lets_in =get_state()inset_state(State.perturbs_in);s_inletenum_bits()=State.enum_bits(perturb_global())()letenum_bool()=State.enum_bool(perturb_global())()letenum_char ()=State.enum_char(perturb_global())()letenum_intbound=State.enum_int(perturb_global())boundlet enum_int32bound=State.enum_int32(perturb_global())boundletenum_int64bound=State.enum_int64(perturb_global())boundletenum_floatbound=State.enum_float(perturb_global())boundletenum_nativeintbound=State.enum_nativeint(perturb_global())bound##V>=4.14##letbits32()=State.bits32(perturb_global())##V>=4.14##letbits64()=State.bits64(perturb_global())##V>=4.14##letnativebits()=State.nativebits(perturb_global())endend