1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071moduleEncoding=structtypet=ASCII|UTF8|UTF16|UTF32|CHAR_WIDTH_1|CHAR_WIDTH_2|CHAR_WIDTH_4letto_string=function|ASCII->"ascii"|UTF8->"utf8"|UTF16->"utf16"|UTF32->"utf32"|CHAR_WIDTH_1->"char_width_1"|CHAR_WIDTH_2->"char_width_2"|CHAR_WIDTH_4->"char_width_4"endtyperuntime_model={exportable_model:string;runtime_model_ptr:string;released:boolref}externalcaml_c_build_exportable_model:string->int->(string*floatoption)list->string="caml_c_build_exportable_model"externalcaml_c_build_runtime_model:string->string="caml_c_build_runtime_model"externalcaml_c_free_runtime_model:string->unit="caml_c_free_runtime_model"externalcaml_c_jaro_winkler_distance:string->float->(floatoption*floatoption*intoption)->runtime_model->string->(string*float)list="caml_c_jaro_winkler_distance"letbuild_exportable_model~encoding?nb_runtime_threads:(nb_runtime_threads=1)candidates=ifnb_runtime_threads<1thenraise(Invalid_argument"nb_runtime_threads must be > 0")elsecaml_c_build_exportable_model(Encoding.to_stringencoding)nb_runtime_threadscandidates(* Shouldn't be called more than once, but we use 'released' to be safe *)letfinalize_runtime_model{runtime_model_ptr;released;_}=match!releasedwith|false->(released:=true;caml_c_free_runtime_modelruntime_model_ptr)|_->()letbuild_runtime_modelexportable_model=letruntime_model_ptr=caml_c_build_runtime_modelexportable_modelin(* We keep a reference to the exportable model because we will need it at runtime *)letruntime_model={exportable_model;runtime_model_ptr;released=reffalse}inGc.finalisefinalize_runtime_modelruntime_model;runtime_modelletjaro_winkler_distance~encoding?min_score:(min_score=(-1.0))?weight:(weight=0.1)?threshold:(threshold=0.7)?n_best_results:(n_best_results=None)runtime_modelinput=ifmin_score<>-1.0&&(min_score<0.0||min_score>1.0)thenraise(Invalid_argument"min_score must be >= 0.0 and <= 1.0")elseifweight<0.0||weight>0.25thenraise(Invalid_argument"weight must be >= 0.0 and <= 0.25")elseifthreshold<0.0||threshold>1.0thenraise(Invalid_argument"threshold must be >= 0.0 and <= 1.0")elsematchn_best_resultswith|Some0->[]|Somexwhenx<0->raise(Invalid_argument"n_best_results must be >= 0")|_->((* We pass the entire runtime model with the exportable model to make sure it is not garbage collected *)caml_c_jaro_winkler_distance(Encoding.to_stringencoding)min_score((Someweight),(Somethreshold),n_best_results)runtime_modelinput)letjaro_distance~encoding?min_score:(min_score=(-1.0))?n_best_results:(n_best_results=None)runtime_modelinput=ifmin_score<>-1.0&&(min_score<0.0||min_score>1.0)thenraise(Invalid_argument"min_score must be >= 0.0 and <= 1.0")elsematchn_best_resultswith|Some0->[]|Somexwhenx<0->raise(Invalid_argument"n_best_results must be >= 0")|_->((* We pass the entire runtime model with the exportable model to make sure it is not garbage collected *)caml_c_jaro_winkler_distance(Encoding.to_stringencoding)min_score(None,None,n_best_results)runtime_modelinput)