/************************************************************************* * * * YAP Prolog @(#)eval.h 1.2 * * * Yap Prolog was developed at NCCUP - Universidade do Porto * * * * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * * * ************************************************************************** * * * File: eval.h * * Last rev: * * mods: * * comments: arithmetical functions info * * * *************************************************************************/ #include /* C library used to implement floating point functions */ #if HAVE_MATH_H #include #endif #ifdef HAVE_FLOAT_H #include #endif #ifdef HAVE_IEEEFP_H #include #endif #ifdef HAVE_LIMITS_H #include #endif #ifdef LONG_MAX #define Int_MAX LONG_MAX #else #define Int_MAX ((Int)((~((CELL)0))>>1)) #endif #ifdef LONG_MIN #define Int_MIN LONG_MIN #else #define Int_MIN (-Int_MAX-(CELL)1) #endif #define PLMAXINT Int_MAX #define PLMININT Int_MIN typedef enum { op_pi, op_e, op_epsilon, op_inf, op_nan, op_random, op_cputime, op_heapused, op_localsp, op_globalsp, op_b, op_env, op_tr, op_stackfree } arith0_op; typedef enum { op_uplus, op_uminus, op_unot, op_exp, op_log, op_log10, op_sqrt, op_sin, op_cos, op_tan, op_sinh, op_cosh, op_tanh, op_asin, op_acos, op_atan, op_asinh, op_acosh, op_atanh, op_floor, op_ceiling, op_round, op_truncate, op_integer, op_float, op_abs, op_lsb, op_msb, op_popcount, op_ffracp, op_fintp, op_sign, op_lgamma, op_erf, op_erfc, op_rational, op_rationalize, op_random1 } arith1_op; typedef enum { op_plus, op_minus, op_times, op_fdiv, op_mod, op_rem, op_div, op_idiv, op_sll, op_slr, op_and, op_or, op_xor, op_atan2, /* C-Prolog exponentiation */ op_power, /* ISO-Prolog exponentiation */ /* op_power, */ op_power2, /* Quintus exponentiation */ /* op_power, */ op_gcd, op_min, op_max, op_rdiv } arith2_op; Functor EvalArg(Term); /* Needed to handle numbers: these two macros are fundamental in the integer/float conversions */ #ifdef C_PROLOG #define FlIsInt(X) ( (X) == (Int)(X) && IntInBnd((X)) ) #else #define FlIsInt(X) ( FALSE ) #endif #ifdef M_WILLIAMS #define MkEvalFl(X) MkFloatTerm(X) #else #define MkEvalFl(X) ( FlIsInt(X) ? MkIntTerm((Int)(X)) : MkFloatTerm(X) ) #endif /* Macros used by some of the eval functions */ #define REvalInt(I) { eval_int = (I); return(FInt); } #define REvalFl(F) { eval_flt = (F); return(FFloat); } #define REvalError() { return(FError); } /* this macro, dependent on the particular implementation is used to interface the arguments into the C libraries */ #ifdef MPW #define FL(X) ((extended)(X)) #else #define FL(X) ((double)(X)) #endif void Yap_InitConstExps(void); void Yap_InitUnaryExps(void); void Yap_InitBinaryExps(void); int Yap_ReInitConstExps(void); int Yap_ReInitUnaryExps(void); int Yap_ReInitBinaryExps(void); Term Yap_eval_atom(Int); Term Yap_eval_unary(Int,Term); Term Yap_eval_binary(Int,Term,Term); Term Yap_InnerEval(Term); Int Yap_ArithError(yap_error_number,Term,char *msg, ...); #include "inline-only.h" INLINE_ONLY inline EXTERN Term Yap_Eval(Term t); INLINE_ONLY inline EXTERN Term Yap_Eval(Term t) { if (t == 0L || ( !IsVarTerm(t) && IsNumTerm(t) )) return t; return Yap_InnerEval(t); } #ifdef P inline static Term Yap_FoundArithError(Term t, Term inp) { CACHE_REGS if (LOCAL_Error_TYPE) { Yap_Error(LOCAL_Error_TYPE, (inp ? inp : LOCAL_Error_Term), LOCAL_ErrorMessage); P = FAILCODE; return 0L; } return t; } #endif #define RINT(v) return(MkIntegerTerm(v)) #define RFLOAT(v) return(MkFloatTerm(v)) #define RBIG(v) return(Yap_MkBigIntTerm(v)) #define RERROR() return(0L) static inline blob_type ETypeOfTerm(Term t) { if (IsIntTerm(t)) return long_int_e; if (IsApplTerm(t)) { Functor f = FunctorOfTerm(t); if (f == FunctorDouble) return double_e; if (f == FunctorLongInt) return long_int_e; if (f == FunctorBigInt) { return big_int_e; } } return db_ref_e; } #if USE_GMP Term Yap_gmq_rdiv_int_int(Int, Int); Term Yap_gmq_rdiv_int_big(Int, Term); Term Yap_gmq_rdiv_big_int(Term, Int); Term Yap_gmq_rdiv_big_big(Term, Term); Term Yap_gmp_add_ints(Int, Int); Term Yap_gmp_sub_ints(Int, Int); Term Yap_gmp_mul_ints(Int, Int); Term Yap_gmp_sll_ints(Int, Int); Term Yap_gmp_add_int_big(Int, Term); Term Yap_gmp_sub_int_big(Int, Term); Term Yap_gmp_sub_big_int(Term, Int); Term Yap_gmp_mul_int_big(Int, Term); Term Yap_gmp_div_int_big(Int, Term); Term Yap_gmp_div_big_int(Term, Int); Term Yap_gmp_div2_big_int(Term, Int); Term Yap_gmp_fdiv_int_big(Int, Term); Term Yap_gmp_fdiv_big_int(Term, Int); Term Yap_gmp_and_int_big(Int, Term); Term Yap_gmp_ior_int_big(Int, Term); Term Yap_gmp_xor_int_big(Int, Term); Term Yap_gmp_sll_big_int(Term, Int); Term Yap_gmp_add_big_big(Term, Term); Term Yap_gmp_sub_big_big(Term, Term); Term Yap_gmp_mul_big_big(Term, Term); Term Yap_gmp_div_big_big(Term, Term); Term Yap_gmp_div2_big_big(Term, Term); Term Yap_gmp_fdiv_big_big(Term, Term); Term Yap_gmp_and_big_big(Term, Term); Term Yap_gmp_ior_big_big(Term, Term); Term Yap_gmp_xor_big_big(Term, Term); Term Yap_gmp_mod_big_big(Term, Term); Term Yap_gmp_mod_big_int(Term, Int); Term Yap_gmp_mod_int_big(Int, Term); Term Yap_gmp_rem_big_big(Term, Term); Term Yap_gmp_rem_big_int(Term, Int); Term Yap_gmp_rem_int_big(Int, Term); Term Yap_gmp_exp_int_int(Int,Int); Term Yap_gmp_exp_int_big(Int,Term); Term Yap_gmp_exp_big_int(Term,Int); Term Yap_gmp_exp_big_big(Term,Term); Term Yap_gmp_gcd_int_big(Int,Term); Term Yap_gmp_gcd_big_big(Term,Term); Term Yap_gmp_big_from_64bits(YAP_LONG_LONG); Term Yap_gmp_float_to_big(Float); Term Yap_gmp_float_to_rational(Float); Term Yap_gmp_float_rationalize(Float); Float Yap_gmp_to_float(Term); Term Yap_gmp_add_float_big(Float, Term); Term Yap_gmp_sub_float_big(Float, Term); Term Yap_gmp_sub_big_float(Term, Float); Term Yap_gmp_mul_float_big(Float, Term); Term Yap_gmp_fdiv_float_big(Float, Term); Term Yap_gmp_fdiv_big_float(Term, Float); int Yap_gmp_cmp_big_int(Term, Int); #define Yap_gmp_cmp_int_big(I, T) (-Yap_gmp_cmp_big_int(T, I)) int Yap_gmp_cmp_big_float(Term, Float); #define Yap_gmp_cmp_float_big(D, T) (-Yap_gmp_cmp_big_float(T, D)) int Yap_gmp_cmp_big_big(Term, Term); int Yap_gmp_tcmp_big_int(Term, Int); #define Yap_gmp_tcmp_int_big(I, T) (-Yap_gmp_tcmp_big_int(T, I)) int Yap_gmp_tcmp_big_float(Term, Float); #define Yap_gmp_tcmp_float_big(D, T) (-Yap_gmp_tcmp_big_float(T, D)) int Yap_gmp_tcmp_big_big(Term, Term); Term Yap_gmp_neg_int(Int); Term Yap_gmp_abs_big(Term); Term Yap_gmp_neg_big(Term); Term Yap_gmp_unot_big(Term); Term Yap_gmp_floor(Term); Term Yap_gmp_ceiling(Term); Term Yap_gmp_round(Term); Term Yap_gmp_trunc(Term); Term Yap_gmp_float_fractional_part(Term); Term Yap_gmp_float_integer_part(Term); Term Yap_gmp_sign(Term); Term Yap_gmp_lsb(Term); Term Yap_gmp_msb(Term); Term Yap_gmp_popcount(Term); char * Yap_gmp_to_string(Term, char *, size_t, int); size_t Yap_gmp_to_size(Term, int); int Yap_term_to_existing_big(Term, MP_INT *); int Yap_term_to_existing_rat(Term, MP_RAT *); void Yap_gmp_set_bit(Int i, Term t); #endif #define Yap_Mk64IntegerTerm(i) __Yap_Mk64IntegerTerm((i) PASS_REGS) INLINE_ONLY inline EXTERN Term __Yap_Mk64IntegerTerm(YAP_LONG_LONG USES_REGS); INLINE_ONLY inline EXTERN Term __Yap_Mk64IntegerTerm(YAP_LONG_LONG i USES_REGS) { if (i <= Int_MAX && i >= Int_MIN) { return MkIntegerTerm((Int)i); } else { #if USE_GMP return Yap_gmp_big_from_64bits(i); #else return MkIntTerm(-1); #endif } } inline static int add_overflow(Int x, Int i, Int j) { return ((i & j & ~x) | (~i & ~j & x)) < 0; } inline static Term add_int(Int i, Int j USES_REGS) { Int x = i+j; #if USE_GMP /* Integer overflow, we need to use big integers */ Int overflow = (i & j & ~x) | (~i & ~j & x); if (overflow < 0) { return(Yap_gmp_add_ints(i, j)); } #endif #ifdef BEAM RINT(x); return( MkIntegerTerm (x)); #else RINT(x); #endif }