Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file fpa_rounding.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266(******************************************************************************)(* *)(* Alt-Ergo: The SMT Solver For Software Verification *)(* Copyright (C) 2013-2018 --- OCamlPro SAS *)(* *)(* This file is distributed under the terms of the license indicated *)(* in the file 'License.OCamlPro'. If 'License.OCamlPro' is not *)(* present, please contact us to clarify licensing. *)(* *)(******************************************************************************)moduleSy=SymbolsmoduleHs=HstringmoduleE=ExpropenOptionsmoduleQ=Numbers.QmoduleZ=Numbers.Zletis_rounding_modet=Options.get_use_fpa()&&matchE.term_viewtwith|E.Term{E.ty=Ty.Tsum(hs,_);_}->String.compare(Hs.viewhs)"fpa_rounding_mode"=0|_->falseletfpa_rounding_mode=letmode_ty=Hs.make"fpa_rounding_mode"inletmode_constrs=[(* standards *)Hs.make"NearestTiesToEven";Hs.make"NearestTiesToAway";Hs.make"ToZero";Hs.make"Up";Hs.make"Down";(* non standards *)Hs.make"Aw";Hs.make"Od";Hs.make"Nodd";Hs.make"Nz";Hs.make"Nd";Hs.make"Nu"]inTy.Tsum(mode_ty,mode_constrs)(* why3/standard rounding modes*)let_NearestTiesToEven__rounding_mode=E.mk_term(Sy.constr"NearestTiesToEven")[]fpa_rounding_mode(** ne in Gappa: to nearest, tie breaking to even mantissas*)let_ToZero__rounding_mode=E.mk_term(Sy.constr"ToZero")[]fpa_rounding_mode(** zr in Gappa: toward zero *)let_Up__rounding_mode=E.mk_term(Sy.constr"Up")[]fpa_rounding_mode(** up in Gappa: toward plus infinity *)let_Down__rounding_mode=E.mk_term(Sy.constr"Down")[]fpa_rounding_mode(** dn in Gappa: toward minus infinity *)let_NearestTiesToAway__rounding_mode=E.mk_term(Sy.constr"NearestTiesToAway")[]fpa_rounding_mode(** na : to nearest, tie breaking away from zero *)(* additional Gappa rounding modes *)let_Aw__rounding_mode=E.mk_term(Sy.constr"Aw")[]fpa_rounding_mode(** aw in Gappa: away from zero **)let_Od__rounding_mode=E.mk_term(Sy.constr"Od")[]fpa_rounding_mode(** od in Gappa: to odd mantissas *)let_No__rounding_mode=E.mk_term(Sy.constr"No")[]fpa_rounding_mode(** no in Gappa: to nearest, tie breaking to odd mantissas *)let_Nz__rounding_mode=E.mk_term(Sy.constr"Nz")[]fpa_rounding_mode(** nz in Gappa: to nearest, tie breaking toward zero *)let_Nd__rounding_mode=E.mk_term(Sy.constr"Nd")[]fpa_rounding_mode(** nd in Gappa: to nearest, tie breaking toward minus infinity *)let_Nu__rounding_mode=E.mk_term(Sy.constr"Nu")[]fpa_rounding_mode(** nu in Gappa: to nearest, tie breaking toward plus infinity *)(** Hepler functions **)letmult_x_by_2_pow_nxn=(* Q.mul_2exp does not support negative i according to Cody ? *)letres1=ifn>=0thenQ.mult_2expxnelseQ.div_2expx(-n)inletres2=Q.multres1Q.onein(* Bug in Zarith according to Cody ? *)assert(Q.equalres1res2);res2letdiv_x_by_2_pow_nxn=mult_x_by_2_pow_nx(-n)lettwo=Q.from_int2lethalf=Q.divQ.onetwotyperounding_mode=(* five standard/why3 fpa rounding modes *)|NearestTiesToEven(*ne in Gappa: to nearest, tie breaking to even mantissas*)|ToZero(* zr in Gappa: toward zero *)|Up(* up in Gappa: toward plus infinity *)|Down(* dn in Gappa: toward minus infinity *)|NearestTiesToAway(* na : to nearest, tie breaking away from zero *)(* additional Gappa rounding modes *)|Aw(* aw in Gappa: away from zero **)|Od(* od in Gappa: to odd mantissas *)|No(* no in Gappa: to nearest, tie breaking to odd mantissas *)|Nz(* nz in Gappa: to nearest, tie breaking toward zero *)|Nd(* nd in Gappa: to nearest, tie breaking toward minus infinity *)|Nu(* nu in Gappa: to nearest, tie breaking toward plus infinity *)(* Integer part of binary logarithm for NON-ZERO POSITIVE number *)letinteger_log_2=letrecauxme=ifQ.comparemtwo>=0thenaux(div_x_by_2_pow_nm1)(e+1)elseifQ.comparemQ.one>=0theneelselet()=assert(Q.compare_to_0m>0)inaux(mult_x_by_2_pow_nm1)(e-1)infunm->ifQ.compare_to_0m<=0thenbeginPrinter.print_err"integer_log_2 not defined for input (%a)"Q.printm;assertfalseend;letres=auxm0in(* Printer.print_dbg
"found that integer_log_2 of %a is %d" Q.print m res;*)assert(Q.compare(mult_x_by_2_pow_nQ.oneres)m<=0);assert(Q.compare(mult_x_by_2_pow_nQ.one(res+1))m>0);resletsigned_oney=lettmp=Q.signyinassert(tmp<>0);iftmp>0thenZ.oneelseZ.m_oneletround_big_intmodey=matchmodewith|Up->Q.num(Q.ceilingy)|Down->Q.num(Q.floory)|ToZero->Q.truncatey|NearestTiesToEven->letz=Q.truncateyinletdiff=Q.abs(Q.suby(Q.from_zz))inifQ.signdiff=0thenzelselettmp=Q.comparediffhalfiniftmp<0thenzelseiftmp>0thenZ.addz(signed_oney)elseifZ.testbitz0thenZ.addz(signed_oney)elsez|NearestTiesToAway->letz=Q.truncateyinletdiff=Q.abs(Q.suby(Q.from_zz))inifQ.signdiff=0thenzelseifQ.comparediffhalf<0thenzelseZ.addz(signed_oney)|Aw|Od|No|Nz|Nd|Nu->assertfalseletto_mantissa_expprecexpmodex=letsign_x=Q.signxinassert((sign_x=0)==Q.equalxQ.zero);ifsign_x=0thenZ.zero,1elseletabs_x=Q.absxinlete=integer_log_2abs_xinlete'=max(e+1-prec)(-exp)inlety=mult_x_by_2_pow_nx(-e')inletr_y=round_big_intmodeyinr_y,e'letmode_of_termt=leteq_ts=E.equalstinifeq_t_NearestTiesToEven__rounding_modethenNearestTiesToEvenelseifeq_t_ToZero__rounding_modethenToZeroelseifeq_t_Up__rounding_modethenUpelseifeq_t_Down__rounding_modethenDownelseifeq_t_NearestTiesToAway__rounding_modethenNearestTiesToAwayelseifeq_t_Aw__rounding_modethenAwelseifeq_t_Od__rounding_modethenOdelseifeq_t_No__rounding_modethenNoelseifeq_t_Nz__rounding_modethenNzelseifeq_t_Nd__rounding_modethenNdelseifeq_t_Nu__rounding_modethenNuelsebeginPrinter.print_err"bad rounding mode %a"E.printt;assertfalseendletint_of_termt=matchE.term_viewtwith|E.Term{E.f=Sy.Intn;_}->letn=Hstring.viewninletn=tryint_of_stringnwith_->Printer.print_err"error when trying to convert %s to an int"n;assertfalseinn(* ! may be negative or null *)|_->Printer.print_err"the given term %a is not an integer"E.printt;assertfalsemoduleMQ=Map.Make(structtypet=E.t*E.t*E.t*Q.tletcompare(prec1,exp1,mode1,x1)(prec2,exp2,mode2,x2)=letc=Q.comparex1x2inifc<>0thencelseletc=E.compareprec1prec2inifc<>0thencelseletc=E.compareexp1exp2inifc<>0thencelseE.comparemode1mode2end)letcache=refMQ.empty(* Compute the floating-point approximation of a rational number *)letfloat_of_rationalprecexpmodex=(* prec = 24 and exp = 149 for 32 bits (or exp = -149 ???) *)letinput=(prec,exp,mode,x)intryMQ.findinput!cachewithNot_found->letmode=mode_of_termmodeinletprec=int_of_termprecinletexp=int_of_termexpinletm,e=to_mantissa_expprecexpmodexinletres=mult_x_by_2_pow_n(Q.from_zm)eincache:=MQ.addinput(res,m,e)!cache;res,m,eletround_to_integermodeq=Q.from_z(round_big_int(mode_of_termmode)q)