123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121(* This file is free software, part of Logtk. See file "license" for more details. *)(** {1 Polynomial} *)moduletypeIntegerModule=sigtypetvalzero:tvalone:tvaladd:t->t->tvalmult:int->t->tvalcompare:t->t->intvalpp:tCCFormat.printerendmoduletypeOrderedType=sigtypetvalcompare:t->t->intvalpp:tCCFormat.printerendmoduletypeS=sigtypettypecoefftypeindetvalconst:coeff->tvalindet:indet->tvaladd:t->t->tvalmult_const:int->t->tvalmult_indet:indet->t->tvalcompare:t->t->intvalequal:t->t->boolvalpp:tCCFormat.printerendmoduleMake(Coeff:IntegerModule)(Indet:OrderedType)=structtypecoeff=Coeff.ttypeindet=Indet.tmoduleMonomial=CCMultiSet.Make(Indet)moduleP=CCMap.Make(Monomial)typet=Coeff.tP.tletconstw=ifw=Coeff.zerothenP.emptyelseP.singletonMonomial.emptywletindetx=P.singleton(Monomial.singletonx)Coeff.oneletaddpq=P.merge_safepq~f:(fun_w->matchwwith|`Leftx|`Rightx->Somex|`Both(w1,w2)->assert(Coeff.addw1w2<>Coeff.zero);Some(Coeff.addw1w2))letmult_constcp=ifc=0thenP.emptyelseP.map(funw->Coeff.multcw)pletmult_indetxp:t=P.fold(funmwnew_p->P.add(Monomial.addmx)wnew_p)pP.emptyletcompare_auxp1p2=(* Comparison result for each monomial *)letmonom_compare:intP.t=P.merge(fun_w1w2->matchw1,w2with|Some_,None->Some1|None,Some_->Some(-1)|Somea1,Somea2->Some(Coeff.comparea1a2)|None,None->None)p1p2in(* Iterate over the monomial results and return
Some 1 or Some -1 if all monomials point in the same direction
Some 0 if there are contradicting monomials
None if all monomials are equal *)letresult=P.fold(fun_cres->matchreswith(* Contradicting monomials already detected *)|Some0->Some0(* Current monomial does not contradict the preliminary result *)|Somerwhen(r<0&&c<=0)||(r>0&&c>=0)->Somer(* Current monomial contradicts the preliminary result *)|Somerwhen(r<0&&c>0)||(r>0&&c<0)->Some0(* All monomials were equal so far *)|Nonewhenc=0->None(* First differing monomial *)|Nonewhenc<>0->Somec(* Exhaustive matching *)|_->assertfalse)monom_compareNoneinresultletcomparep1p2=beginmatchcompare_auxp1p2with|Somer->r|None->0endletequalp1p2=(compare_auxp1p2=None)letmonomial_ppout(a:Monomial.t):unit=Format.fprintfout"(%a)"(Util.pp_list~sep:"*"Indet.pp)(Monomial.to_lista)letppout(a:t):unit=Format.fprintfout"Poly[%a]"(Util.pp_list~sep:" + "(CCPair.pp~pp_sep:(CCFormat.return"@ * ")monomial_ppCoeff.pp))(P.bindingsa)end