123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat a l'energie atomique et aux energies *)(* alternatives) *)(* *)(* 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, version 2.1. *)(* *)(* It 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. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)openQedopenLogicopenLangopenLang.Fletf_builtin~library?(injective=false)?(result=Real)?(params=[Real])?extname=assert(name.[0]=='\\');letcall=matchextwithSomecall->call|None->String.subname1(String.lengthname-1)inletlink=Engine.F_callcallinletcategory=letopenQed.LogicinifinjectivethenInjectionelseFunctioninletsignature=List.mapLogicBuiltins.kind_of_tauparamsinletparams=List.mapKind.of_tauparamsinletlfun=extern_s~library~category~result~params~linknameinLogicBuiltins.(add_builtinnamesignaturelfun);lfun(* -------------------------------------------------------------------------- *)(* --- Real Of Int --- *)(* -------------------------------------------------------------------------- *)letf_real_of_int=extern_f~library:"qed"~category:Qed.Logic.Injection~result:Logic.Real~params:[Logic.Sint]"real_of_int"letbuiltin_real_of_inte=matchF.reprewith|Qed.Logic.Kintk->F.e_real(Q.of_bigintk)|_->raiseNot_found(* -------------------------------------------------------------------------- *)(* --- Truncate --- *)(* -------------------------------------------------------------------------- *)letf_truncate=f_builtin~library:"truncate"~result:Int"\\truncate"letf_ceil=f_builtin~library:"truncate"~result:Int"\\ceil"letf_floor=f_builtin~library:"truncate"~result:Int"\\floor"letbuiltin_truncatefe=letopenQed.LogicinmatchF.reprewith|Kint_->e|KrealrwhenQ.(equalrzero)->e_zero|Krealr->begintry(* Waiting for Z-Arith to have truncation to big-int *)lettruncated=int_of_float(Q.to_floatr)inletreversed=Q.of_inttruncatedinletbase=F.e_inttruncatedinifQ.equalrreversedthenbaseelseiff==f_ceil&&Q.(ltzeror)thenF.(e_addbasee_one)elseiff==f_floor&&Q.(ltrzero)thenF.(e_subbasee_one)elsebasewith_->raiseNot_foundend|Fun(f,[e])whenf==f_real_of_int->e|_->raiseNot_found(* -------------------------------------------------------------------------- *)(* --- Conversions --- *)(* -------------------------------------------------------------------------- *)letint_of_realx=e_funf_truncate[x]letreal_of_intx=e_funf_real_of_int[x]letint_of_boola=e_neqaF.e_zero(* if a != 0 then true else false *)letbool_of_inta=e_ifaF.e_oneF.e_zero(* if a then 1 else 0 *)(* -------------------------------------------------------------------------- *)(* --- Sign --- *)(* -------------------------------------------------------------------------- *)(* rewrite a=b when a or b is f(x)
for functions f such as 0 <= f(x) && ( f(x) = 0 <-> x = 0 ) *)letbuiltin_positive_eqlfun~domain~zero~injectiveab=letopenQed.LogicinbeginmatchF.repra,F.reprbwith|Fun(f,[a]),Fun(f',[b])wheninjective&&f==lfun&&f'==lfun&&domaina&&domainb->(* injective a in domain && b in domain -> ( f(a) = f(b) <-> a = b ) *)e_eqab|Fun(f,[a]),_whenf==lfun&&domaina->ifQED.eval_ltbzerothen(* a in domain && b < 0 -> ( f(a) = b <-> false ) *)e_falseelseifQED.eval_eqzerobthen(* a in domain && b = 0 -> ( f(a) = 0 <-> a = 0 ) *)e_eqazeroelseraiseNot_found|_->raiseNot_foundend(* rewrite a<=b when a or b is f(x)
for functions f such as 0 <= f(x) && f(x) = 0 <-> x = 0 *)letbuiltin_positive_leqlfun~domain~zero~monotonicab=letopenQed.LogicinbeginmatchF.repra,F.reprbwith|Fun(f,[a]),Fun(f',[b])whenmonotonic&&f==lfun&&f'==lfun&&domaina&&domainb->(* increasing && a in domain && b in domain -> ( f(a) <= f(b) <-> a <= b) *)e_leqab|Fun(f,[a]),_whenf==lfun&&domaina->ifQED.eval_ltbzerothen(* a in domain && b < 0 -> ( f(a) <= b <-> false ) *)e_falseelseifQED.eval_eqzerobthen(* a in domain && b = 0 -> ( f(a) <= b <-> a = 0 )*)e_eqazeroelseraiseNot_found|_,Fun(f,[b])whenf==lfun&&domainb&&QED.eval_leqazero->(* b in domain && a <= 0 -> ( a <= f(b) <-> true *)e_true|_->raiseNot_foundend(* rewrite a=b when a or b is f(x)
for functions f such as 0 < f(x) *)letbuiltin_strict_eqlfun~domain~zero~injectiveab=letopenQed.LogicinbeginmatchF.repra,F.reprbwith|Fun(f,[a]),Fun(f',[b])wheninjective&&f==lfun&&f'==lfun&&domaina&&domainb->(* injective && a in domain && b in domain -> ( f(a) = f(b) <-> a = b ) *)e_eqab|Fun(f,[a]),_whenf==lfun&&domaina&&QED.eval_leqbzero->(* a in domain && b <= 0 -> ( f(a) = b <-> false ) *)e_false|_->raiseNot_foundend(* rewrite a<=b when a or b is f(x)
for functions f such as 0 < f(x) *)letbuiltin_strict_leqlfun~domain~zero~monotonicab=letopenQed.LogicinbeginmatchF.repra,F.reprbwith|Fun(f,[a]),Fun(f',[b])whenmonotonic&&f==lfun&&f'==lfun&&domaina&&domainb->(* increasing && a in domain && b in domain -> ( f(a) <= f(b) <-> a <= b ) *)e_leqab|Fun(f,[a]),_whenf==lfun&&domaina&&QED.eval_leqbzero->(* a in domain && b <= 0 -> ( f(a) <= b <-> false ) *)e_false|_,Fun(f,[b])whenf==lfun&&domainb&&QED.eval_leqazero->(* b in domain && a <= 0 -> ( a <= f(b) <-> true ) *)e_true|_->raiseNot_foundend(* -------------------------------------------------------------------------- *)(* --- Absolute --- *)(* -------------------------------------------------------------------------- *)letf_iabs=extern_f~library:"cmath"~link:(Qed.Engine.F_call"IAbs.abs")"\\iabs"letf_rabs=extern_f~library:"cmath"~result:Real~params:[Sreal]~link:(Qed.Engine.F_call"RAbs.abs")"\\rabs"let()=beginLogicBuiltins.(add_builtin"\\abs"[Z]f_iabs);LogicBuiltins.(add_builtin"\\abs"[R]f_rabs);endletdomain_abs_x=trueletbuiltin_absfze=letopenQed.LogicinmatchF.reprewith|Times(k,a)->e_times(Integer.absk)(e_funf[a])|Kintk->e_zint(Integer.absk)|KrealrwhenQ.ltrQ.zero->e_real(Q.negr)|_->matchis_true(e_leqze)with|Yes->e|No->e_oppe|Maybe->raiseNot_foundletbuiltin_iabs_eq=builtin_positive_eqf_iabs~domain:domain_abs~zero:e_zero~injective:falseletbuiltin_iabs_leq=builtin_positive_leqf_iabs~domain:domain_abs~zero:e_zero~monotonic:falseletbuiltin_rabs_eq=builtin_positive_eqf_rabs~domain:domain_abs~zero:e_zero_real~injective:falseletbuiltin_rabs_leq=builtin_positive_leqf_rabs~domain:domain_abs~zero:e_zero_real~monotonic:false(* -------------------------------------------------------------------------- *)(* --- Square Root --- *)(* -------------------------------------------------------------------------- *)letf_sqrt=f_builtin~library:"sqrt""\\sqrt"letdomain_sqrtx=QED.eval_leqe_zero_realxletbuiltin_sqrte=letopenQed.LogicinmatchF.reprewith|Krealrwhenr==Q.zero->F.e_zero_real(* srqt(0)==0 *)|Krealrwhenr==Q.one->F.e_one_real(* srqt(1)==1 *)|Mul[a;b]wheneval_eqab->(* a==b ==> sqrt(a*b)==|a| *)e_funf_rabs[a](* a is smaller *)|_->raiseNot_foundletbuiltin_sqrt_eq=builtin_positive_eqf_sqrt~domain:domain_sqrt~zero:e_zero_real~injective:trueletbuiltin_sqrt_leq=builtin_positive_leqf_sqrt~domain:domain_sqrt~zero:e_zero_real~monotonic:true(* -------------------------------------------------------------------------- *)(* --- Exponential --- *)(* -------------------------------------------------------------------------- *)letf_exp=f_builtin~library:"exponential"~injective:true"\\exp"letf_log=f_builtin~library:"exponential""\\log"letf_log10=f_builtin~library:"exponential""\\log10"letf_pow=f_builtin~library:"power"~params:[Real;Real]"\\pow"let()=ignoref_log10letdomain_exp_x=trueletdomain_logx=QED.eval_lte_zero_realxletbuiltin_expe=letopenQed.LogicinmatchF.reprewith|Krealrwhenr==Q.zero->F.e_one_real(* exp(0)==1 *)|Times(n,r)whenn==Z.minus_one->(* exp(-r) = 1/exp(r) *)F.e_divF.e_one_real(F.e_funf_exp[r])|Fun(f,[x])whenf==f_log&&domain_logx->(* 0<x ==> exp(log(x)) = x *)x|_->raiseNot_foundletbuiltin_loge=letopenQed.LogicinmatchF.reprewith|Krealrwhenr==Q.one->F.e_zero_real(* log(1) == 0 *)|Fun(f,[x])whenf==f_exp->x(* log(exp(x)) == x *)|Fun(f,[x;n])whenf==f_pow&&domain_logx->(* 0<x ==> log(x^n) == n*log(x) *)F.e_muln(F.e_funf_log[x])|_->raiseNot_found(* a^n = e^(n.log a) *)letbuiltin_powan=letopenQed.LogicinmatchF.reprnwith|KrealrwhenQ.(equalrzero)->F.e_one_real(* a^0 == 1 *)|KrealrwhenQ.(equalrone)->a(* a^1 == a *)|_->raiseNot_foundletbuiltin_exp_eq=builtin_strict_eqf_exp~domain:domain_exp~zero:e_zero_real~injective:trueletbuiltin_exp_leq=builtin_strict_leqf_exp~domain:domain_exp~zero:e_zero_real~monotonic:true(* -------------------------------------------------------------------------- *)(* --- Trigonometry --- *)(* -------------------------------------------------------------------------- *)letf_sin=f_builtin~library:"trigonometry""\\sin"letf_cos=f_builtin~library:"trigonometry""\\cos"letf_tan=f_builtin~library:"trigonometry""\\tan"letf_asin=f_builtin~library:"arctrigo""\\asin"letf_acos=f_builtin~library:"arctrigo""\\acos"letf_atan=f_builtin~library:"arctrigo"~injective:true"\\atan"letdomain_asin_acosx=QED.eval_leqxe_one_real&&QED.eval_leqe_minus_one_realxletdomain_atan_x=trueletbuiltin_trigof_arc~domaine=matchF.reprewith|Fun(f,[x])whenf==f_arc&&domainx->x|_->raiseNot_found(* -------------------------------------------------------------------------- *)(* --- Hyperbolic --- *)(* -------------------------------------------------------------------------- *)let()=beginignore(f_builtin~library:"hyperbolic""\\sinh");ignore(f_builtin~library:"hyperbolic""\\cosh");ignore(f_builtin~library:"hyperbolic""\\tanh");end(* -------------------------------------------------------------------------- *)(* --- Polar Coordinates --- *)(* -------------------------------------------------------------------------- *)let()=beginignore(f_builtin~library:"polar"~params:[Real;Real]"\\atan2");ignore(f_builtin~library:"polar"~params:[Real;Real]"\\hypot");end(* -------------------------------------------------------------------------- *)(* --- Registry --- *)(* -------------------------------------------------------------------------- *)let()=Context.registerbeginfun()->F.set_builtin_1f_real_of_intbuiltin_real_of_int;F.set_builtin_1f_truncate(builtin_truncatef_truncate);F.set_builtin_1f_ceil(builtin_truncatef_ceil);F.set_builtin_1f_floor(builtin_truncatef_floor);F.set_builtin_1f_iabs(builtin_absf_iabse_zero);F.set_builtin_1f_rabs(builtin_absf_rabse_zero_real);F.set_builtin_eqf_iabsbuiltin_iabs_eq;F.set_builtin_eqf_rabsbuiltin_rabs_eq;F.set_builtin_leqf_iabsbuiltin_iabs_leq;F.set_builtin_leqf_rabsbuiltin_rabs_leq;F.set_builtin_1f_sqrtbuiltin_sqrt;F.set_builtin_eqf_sqrtbuiltin_sqrt_eq;F.set_builtin_leqf_sqrtbuiltin_sqrt_leq;F.set_builtin_1f_logbuiltin_log;F.set_builtin_1f_expbuiltin_exp;F.set_builtin_eqf_expbuiltin_exp_eq;F.set_builtin_leqf_expbuiltin_exp_leq;F.set_builtin_2f_powbuiltin_pow;F.set_builtin_1f_sin(builtin_trigof_asin~domain:domain_asin_acos);F.set_builtin_1f_cos(builtin_trigof_acos~domain:domain_asin_acos);F.set_builtin_1f_tan(builtin_trigof_atan~domain:domain_atan);end(* -------------------------------------------------------------------------- *)