123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)openNamesopenGlob_term(* Poor's man DECLARE PLUGIN *)let__coq_plugin_name="float_syntax_plugin"let()=Mltop.add_known_module__coq_plugin_name(*** Constants for locating float constructors ***)letmake_dirl=DirPath.make(List.rev_mapId.of_stringl)letmake_pathdirid=Libnames.make_path(make_dirdir)(Id.of_stringid)(*** Parsing for float in digital notation ***)letwarn_inexact_float=CWarnings.create~name:"inexact-float"~category:"parsing"(fun(sn,f)->Pp.strbrk(Printf.sprintf"The constant %s is not a binary64 floating-point value. \
A closest value %s will be used and unambiguously printed %s."sn(Float64.to_hex_stringf)(Float64.to_stringf)))letinterp_float?locn=letsn=NumTok.Signed.to_stringninletf=Float64.of_stringsnin(* return true when f is not exactly equal to n,
this is only used to decide whether or not to display a warning
and does not play any actual role in the parsing *)letinexact()=matchFloat64.classifyfwith|Float64.(PInf|NInf|NaN)->true|Float64.(PZero|NZero)->not(NumTok.Signed.is_zeron)|Float64.(PNormal|NNormal|PSubn|NSubn)->letm,e=let(_,i),f,e=NumTok.Signed.to_int_frac_and_exponentninleti=NumTok.UnsignedNat.to_stringiinletf=matchfwith|None->""|Somef->NumTok.UnsignedNat.to_stringfinlete=matchewith|None->"0"|Somee->NumTok.SignedNat.to_stringeinZ.of_string(i^f),(tryint_of_stringewithFailure_->0)-String.lengthfinletm',e'=letm',e'=Float64.frshiftexpfinletm'=Float64.normfr_mantissam'inlete'=Uint63.to_int_mine'4096-Float64.eshift-53inZ.of_string(Uint63.to_stringm'),e'inletc2,c5=Z.(of_int2,of_int5)in(* check m*5^e <> m'*2^e' *)letcheckmem'e'=not(Z.(equal(mulm(powc5e))(mulm'(powc2e'))))in(* check m*5^e*2^e' <> m' *)letcheck'mee'm'=not(Z.(equal(mul(mulm(powc5e))(powc2e'))m'))in(* we now have to check m*10^e <> m'*2^e' *)ife>=0thenife<=e'thencheckmem'(e'-e)elsecheck'me(e-e')m'else(* e < 0 *)ife'<=ethencheckm'(-e)m(e-e')elsecheck'm'(-e)(e'-e)minifNumTok.(Signed.classifyn=CDec)&&inexact()thenwarn_inexact_float?loc(sn,f);DAst.make?loc(GFloatf)(* Pretty printing is already handled in constrextern.ml *)letuninterp_float_=None(* Actually declares the interpreter for float *)openNotationletat_declare_ml_modulefx=Mltop.declare_cache_obj(fun()->fx)__coq_plugin_nameletfloat_module=["Coq";"Floats";"PrimFloat"]letfloat_path=make_pathfloat_module"float"letfloat_scope="float_scope"let_=register_rawnumeral_interpretationfloat_scope(interp_float,uninterp_float);at_declare_ml_moduleenable_prim_token_interpretation{pt_local=false;pt_scope=float_scope;pt_interp_info=Uidfloat_scope;pt_required=(float_path,float_module);pt_refs=[];pt_in_match=false}