123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356open!Baseopen!Binary_searchableincludeTest_binary_searchable_intfmoduletypeS_gen=sigopenBinary_searchabletype'attype'aeltvalbinary_search:('at,'aelt,'aelt)binary_searchvalbinary_search_segmented:('at,'aelt)binary_search_segmentedendmoduletypeIndexable_gen_and_for_test=sigincludeS_genmoduleFor_test:sigvalcompare:boolelt->boolelt->intvalsmall:booleltvalbig:booleltvalof_array:booleltarray->booltendendmoduleTest_gen(M:Indexable_gen_and_for_test)=structopenMlet%test_module"test_binary_searchable"=(modulestructletcompare=For_test.compareletelt_compare=For_test.comparelets=For_test.smallletb=For_test.bigletbinary_search?pos?len~comparethowv=binary_search?pos?len~compare(For_test.of_arrayt)howv;;let(=)=Poly.equallet%test_=binary_search~compare[||]`First_equal_tos=Nonelet%test_=binary_search~compare[|s|]`First_equal_tos=Some0let%test_=binary_search~compare[|s|]`First_equal_tob=Nonelet%test_=binary_search~compare[|s;b|]`First_equal_tos=Some0let%test_=binary_search~compare[|s;b|]`First_equal_tob=Some1let%test_=binary_search~compare[|b;b|]`First_equal_tos=Nonelet%test_=binary_search~compare[|s;s|]`First_equal_tob=Nonelet%test_=binary_search~compare[|s;b;b|]`First_equal_tob=Some1let%test_=binary_search~compare[|s;s;b|]`First_equal_tos=Some0let%test_=binary_search~compare[|b;b;b|]`First_equal_tos=Nonelet%test_=binary_search~compare[||]`Last_equal_tos=Nonelet%test_=binary_search~compare[|s|]`Last_equal_tos=Some0let%test_=binary_search~compare[|s|]`Last_equal_tob=Nonelet%test_=binary_search~compare[|s;b|]`Last_equal_tob=Some1let%test_=binary_search~compare[|s;b|]`Last_equal_tos=Some0let%test_=binary_search~compare[|b;b|]`Last_equal_tos=Nonelet%test_=binary_search~compare[|s;s|]`Last_equal_tob=Nonelet%test_=binary_search~compare[|s;b;b|]`Last_equal_tob=Some2let%test_=binary_search~compare[|s;s;b|]`Last_equal_tos=Some1let%test_=binary_search~compare[|b;b;b|]`Last_equal_tos=Nonelet%test_=binary_search~compare[||]`First_greater_than_or_equal_tos=Nonelet%test_=binary_search~compare[|b|]`First_greater_than_or_equal_tos=Some0;;let%test_=binary_search~compare[|s|]`First_greater_than_or_equal_tos=Some0;;let%test_=binary_search~compare[|s|]`First_strictly_greater_thans=Nonelet%test_=binary_search~compare[||]`Last_less_than_or_equal_tos=Nonelet%test_=binary_search~compare[|b|]`Last_less_than_or_equal_tos=Nonelet%test_=binary_search~compare[|s|]`Last_less_than_or_equal_tos=Some0let%test_=binary_search~compare[|s|]`Last_strictly_less_thans=Noneletcreate_test_case(num_s,num_b)=letarr=Array.createb~len:(num_s+num_b)infori=0tonum_s-1doarr.(i)<-sdone;arr;;letonly_small=10_000,0letonly_big=0,10_000letboth=2531,4717let%test_=matchbinary_search(create_test_caseonly_small)~compare`First_equal_toswith|None->false|Some_->true;;let%test_=letarr=create_test_casebothinmatchbinary_searcharr~compare`First_equal_tobwith|None->false|Somev->v=2531;;let%test_=letarr=create_test_caseonly_smallinbinary_searcharr~compare`First_equal_tob=None;;letcreate_deterministic_test()=Array.init100_000~f:(funi->ifi>50_000thenbelses);;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`First_equal_tos=Some0;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`Last_equal_tos=Some50_000;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`First_greater_than_or_equal_tos=Some0;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`Last_less_than_or_equal_tos=Some50_000;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`First_strictly_greater_thans=Some50_001;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`Last_strictly_less_thanb=Some50_000;;(* tests around a gap*)let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`First_equal_tob=Some50_001;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`Last_equal_tob=Some99_999;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`First_greater_than_or_equal_tob=Some50_001;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`Last_less_than_or_equal_tob=Some99_999;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`First_strictly_greater_thanb=None;;let%test_=letarr=create_deterministic_test()inbinary_searcharr~compare`Last_strictly_less_thanb=Some50_000;;(* test beginning of array *)let%test_=letarr=create_test_caseonly_biginbinary_searcharr~compare`First_equal_tos=None;;let%test_=letarr=create_test_caseonly_biginbinary_searcharr~compare`Last_equal_tos=None;;let%test_=letarr=create_test_caseonly_biginbinary_searcharr~compare`First_greater_than_or_equal_tos=Some0;;let%test_=letarr=create_test_caseonly_biginbinary_searcharr~compare`Last_less_than_or_equal_tos=None;;let%test_=letarr=create_test_caseonly_biginbinary_searcharr~compare`First_strictly_greater_thans=Some0;;let%test_=letarr=create_test_caseonly_biginbinary_searcharr~compare`Last_strictly_less_thanb=None;;(* test end of array *)let%test_=letarr=create_test_caseonly_smallinbinary_searcharr~compare`First_equal_tob=None;;let%test_=letarr=create_test_caseonly_smallinbinary_searcharr~compare`Last_equal_tob=None;;let%test_=letarr=create_test_caseonly_smallinbinary_searcharr~compare`First_greater_than_or_equal_tob=None;;let%test_=letarr=create_test_caseonly_smallinbinary_searcharr~compare`Last_less_than_or_equal_tob=Some9_999;;let%test_=letarr=create_test_caseonly_smallinbinary_searcharr~compare`First_strictly_greater_thans=None;;let%test_=letarr=create_test_caseonly_smallinbinary_searcharr~compare`Last_strictly_less_thanb=Some9_999;;let%test_unit_=forlength=0to5dofornum_s=0tolengthdoletarr=Array.initlength~f:(funi->ifi<num_sthenselseb)inforpos=-1tolengthdoforlen=-1tolength+1do(*try*)letshould_raise=Exn.does_raise(fun()->Ordered_collection_common.check_pos_len_exn~pos~len~total_length:length)inletresult=Result.try_with(fun()->binary_searcharr~pos~len~compare:elt_compare`Last_equal_tos)inmatchshould_raise,resultwith|true,Error_->()|true,Ok_->failwith"expected it to raise but it didn't"|false,Error_->failwith"expected it to not raise, but it raised"|false,Okresult->letsearched=num_s-1inletcorrect_result=ifsearched<posthenNoneelseiflen=0thenNoneelseifsearched>=pos+lenthenSome(pos+len-1)elseSomesearchedinifnot(correct_result=result)thenfailwith"Wrong result"(*with exn ->
failwiths "binary_search bug"
(exn, `length length, `search_key search_key, `pos pos, `len len)
<:sexp_of< exn * [ `length of int ] * [ `search_key of int ]
* [ `pos of int ] * [ `len of int ] >>*)donedonedonedone;;letbinary_search_segmenteda=binary_search_segmented(For_test.of_arraya)(*test for binary_search_segmented*)let%test_=letarr=create_deterministic_test()inletsegment_ofx=ifx=bthen`Rightelse`Leftinbinary_search_segmentedarr~segment_of`Last_on_left=Some50_000&&binary_search_segmentedarr~segment_of`First_on_right=Some50_001;;let%test_=letarr=create_deterministic_test()inletsegment_of_=`Rightinbinary_search_segmentedarr~segment_of`Last_on_left=None&&binary_search_segmentedarr~segment_of`First_on_right=Some0;;let%test_=letarr=create_deterministic_test()inletsegment_of_=`Leftinbinary_search_segmentedarr~segment_of`Last_on_left=Some99_999&&binary_search_segmentedarr~segment_of`First_on_right=None;;end);;endmoduleTest(M:Binary_searchable_and_for_test)=Test_gen(structtype'at=M.ttype'aelt=M.eltletbinary_search=M.binary_searchletbinary_search_segmented=M.binary_search_segmentedmoduleFor_test=M.For_testend)moduleTest1(M:Binary_searchable1_and_for_test)=Test_gen(structtype'at='aM.ttype'aelt='aletbinary_search=M.binary_searchletbinary_search_segmented=M.binary_search_segmentedmoduleFor_test=structletof_array=M.For_test.of_arrayletcompare=Bool.compareletsmall=falseletbig=trueendend)moduleMake_and_test(M:Indexable_and_for_test)=structmoduleB=Binary_searchable.Make(M)includeBincludeTest(structtypet=M.ttypeelt=M.eltincludeBmoduleFor_test=M.For_testend)endmoduleMake1_and_test(M:Indexable1_and_for_test)=structmoduleB=Binary_searchable.Make1(M)includeBincludeTest1(structtype'at='aM.tincludeBmoduleFor_test=M.For_testend)end