From 853fa92d50c7bae63248b453bfd4ebea0d1cd61f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sun, 26 Apr 2020 02:24:17 +0200 Subject: [PATCH] kernel: add some 'missing' methods for machine floats - A bunch of operations for floating point numbers had no implementation for machine floats, even though C99 provides suitable functions. - Most of the math functions we checked for in configure are actually guaranteed to be there by C99. The sole exception is exp10, which is a non-standard extension. - Add a bunch of super-trivial tests to ensure those new functions are actually callable. These are not good tests, just a bare minimum. --- configure.ac | 4 +- lib/float.gd | 8 ++-- lib/ieee754.g | 41 ++++++++++-------- src/macfloat.c | 54 +++++++++++++---------- tst/testinstall/float.tst | 91 ++++++++++++++++++++++++++++++++++++--- 5 files changed, 146 insertions(+), 52 deletions(-) diff --git a/configure.ac b/configure.ac index 5b47c2de27..07697e852c 100644 --- a/configure.ac +++ b/configure.ac @@ -950,8 +950,8 @@ AC_SEARCH_LIBS([cos], [m], [], [ AC_MSG_ERROR([unable to find the cos() function]) ]) -dnl check for math functions -AC_CHECK_FUNCS([log2 log10 log1p exp2 expm1 exp10 trunc]) +dnl check for non-standard math functions +AC_CHECK_FUNCS([exp10]) dnl pthreads AS_IF([test "x$enable_hpcgap" = xyes],[ diff --git a/lib/float.gd b/lib/float.gd index fa3f1af0e4..100e7bd5aa 100644 --- a/lib/float.gd +++ b/lib/float.gd @@ -51,8 +51,8 @@ end); ## <#GAPDoc Label="Float-Math-Commands"> ## ## Standard mathematical operations -## ## +## ## ## ## @@ -60,8 +60,8 @@ end); ## ## ## -## ## +## ## ## ## @@ -79,16 +79,16 @@ end); ## ## ## +## +## ## ## ## ## -## ## ## ## ## -## ## ## ## diff --git a/lib/ieee754.g b/lib/ieee754.g index 4a173c08c3..42985c75a2 100644 --- a/lib/ieee754.g +++ b/lib/ieee754.g @@ -61,39 +61,44 @@ InstallMethod( Int, "for macfloats", true, [ IsIEEE754FloatRep ], 0, INTFLOOR_MA InstallMethod( Sin, "for macfloats", [ IsIEEE754FloatRep ], SIN_MACFLOAT ); InstallMethod( Cos, "for macfloats", [ IsIEEE754FloatRep ], COS_MACFLOAT ); InstallMethod( Tan, "for macfloats", [ IsIEEE754FloatRep ], TAN_MACFLOAT ); -InstallMethod( Acos, "for macfloats", [ IsIEEE754FloatRep ], ACOS_MACFLOAT ); InstallMethod( Asin, "for macfloats", [ IsIEEE754FloatRep ], ASIN_MACFLOAT ); +InstallMethod( Acos, "for macfloats", [ IsIEEE754FloatRep ], ACOS_MACFLOAT ); InstallMethod( Atan, "for macfloats", [ IsIEEE754FloatRep ], ATAN_MACFLOAT ); -InstallMethod( Atan2, "for macfloats", [ IsIEEE754FloatRep, IsIEEE754FloatRep ], ATAN2_MACFLOAT ); + +InstallMethod( Sinh, "for macfloats", [ IsIEEE754FloatRep ], SINH_MACFLOAT ); +InstallMethod( Cosh, "for macfloats", [ IsIEEE754FloatRep ], COSH_MACFLOAT ); +InstallMethod( Tanh, "for macfloats", [ IsIEEE754FloatRep ], TANH_MACFLOAT ); +InstallMethod( Asinh, "for macfloats", [ IsIEEE754FloatRep ], ASINH_MACFLOAT ); +InstallMethod( Acosh, "for macfloats", [ IsIEEE754FloatRep ], ACOSH_MACFLOAT ); +InstallMethod( Atanh, "for macfloats", [ IsIEEE754FloatRep ], ATANH_MACFLOAT ); + InstallMethod( Log, "for macfloats", [ IsIEEE754FloatRep ], LOG_MACFLOAT ); +InstallMethod( Log2, "for macfloats", [ IsIEEE754FloatRep ], LOG2_MACFLOAT ); +InstallMethod( Log10, "for macfloats", [ IsIEEE754FloatRep ], LOG10_MACFLOAT ); +InstallMethod( Log1p, "for macfloats", [ IsIEEE754FloatRep ], LOG1P_MACFLOAT ); + InstallMethod( Exp, "for macfloats", [ IsIEEE754FloatRep ], EXP_MACFLOAT ); -if IsBound(LOG2_MACFLOAT) then - InstallMethod( Log2, "for macfloats", [ IsIEEE754FloatRep ], LOG2_MACFLOAT ); -fi; -if IsBound(LOG10_MACFLOAT) then - InstallMethod( Log10, "for macfloats", [ IsIEEE754FloatRep ], LOG10_MACFLOAT ); -fi; -if IsBound(LOG1P_MACFLOAT) then - InstallMethod( Log1p, "for macfloats", [ IsIEEE754FloatRep ], LOG1P_MACFLOAT ); -fi; -if IsBound(EXP2_MACFLOAT) then - InstallMethod( Exp2, "for macfloats", [ IsIEEE754FloatRep ], EXP2_MACFLOAT ); -fi; -if IsBound(EXPM1_MACFLOAT) then - InstallMethod( Expm1, "for macfloats", [ IsIEEE754FloatRep ], EXPM1_MACFLOAT ); -fi; +InstallMethod( Exp2, "for macfloats", [ IsIEEE754FloatRep ], EXP2_MACFLOAT ); +InstallMethod( Expm1, "for macfloats", [ IsIEEE754FloatRep ], EXPM1_MACFLOAT ); if IsBound(EXP10_MACFLOAT) then InstallMethod( Exp10, "for macfloats", [ IsIEEE754FloatRep ], EXP10_MACFLOAT ); fi; InstallMethod( Sqrt, "for macfloats", [ IsIEEE754FloatRep ], SQRT_MACFLOAT ); +InstallMethod( CubeRoot, "for macfloats", [ IsIEEE754FloatRep ], CBRT_MACFLOAT ); + +InstallMethod( Atan2, "for macfloats", [ IsIEEE754FloatRep, IsIEEE754FloatRep ], ATAN2_MACFLOAT ); +InstallMethod( Hypothenuse, "for macfloats", [ IsIEEE754FloatRep, IsIEEE754FloatRep ], HYPOT_MACFLOAT ); + +InstallMethod( Erf, "for macfloats", [ IsIEEE754FloatRep ], ERF_MACFLOAT ); +InstallMethod( Gamma, "for macfloats", [ IsIEEE754FloatRep ], GAMMA_MACFLOAT ); + InstallMethod( Round, "for macfloats", [ IsIEEE754FloatRep ], RINT_MACFLOAT ); InstallMethod( Floor, "for macfloats", [ IsIEEE754FloatRep ], FLOOR_MACFLOAT ); InstallMethod( Ceil, "for macfloats", [ IsIEEE754FloatRep ], CEIL_MACFLOAT ); InstallMethod( AbsoluteValue, "for macfloats", [ IsIEEE754FloatRep ], ABS_MACFLOAT ); InstallMethod( SignFloat, "for macfloats", [ IsIEEE754FloatRep ], SIGN_MACFLOAT ); InstallMethod( SignBit, "for macfloats", [ IsIEEE754FloatRep ], SIGNBIT_MACFLOAT ); -InstallMethod( Hypothenuse, "for macfloats", [ IsIEEE754FloatRep, IsIEEE754FloatRep ], HYPOT_MACFLOAT ); InstallMethod( LdExp, "for macfloat,int", [ IsIEEE754FloatRep, IsInt ], LDEXP_MACFLOAT ); InstallMethod( FrExp, "for macfloat", [ IsIEEE754FloatRep ], FREXP_MACFLOAT ); InstallMethod( EqFloat, "for macfloats", [ IsIEEE754FloatRep, IsIEEE754FloatRep ], EQ_MACFLOAT ); diff --git a/src/macfloat.c b/src/macfloat.c index 5e1a50b1b1..a16781dd61 100644 --- a/src/macfloat.c +++ b/src/macfloat.c @@ -398,27 +398,28 @@ MAKEMATHPRIMITIVE(TAN,tan) MAKEMATHPRIMITIVE(ACOS,acos) MAKEMATHPRIMITIVE(ASIN,asin) MAKEMATHPRIMITIVE(ATAN,atan) + +MAKEMATHPRIMITIVE(COSH,cosh) +MAKEMATHPRIMITIVE(SINH,sinh) +MAKEMATHPRIMITIVE(TANH,tanh) +MAKEMATHPRIMITIVE(ACOSH,acosh) +MAKEMATHPRIMITIVE(ASINH,asinh) +MAKEMATHPRIMITIVE(ATANH,atanh) + MAKEMATHPRIMITIVE(LOG,log) -MAKEMATHPRIMITIVE(EXP,exp) -#ifdef HAVE_LOG2 MAKEMATHPRIMITIVE(LOG2,log2) -#endif -#ifdef HAVE_LOG10 MAKEMATHPRIMITIVE(LOG10,log10) -#endif -#ifdef HAVE_LOG1P MAKEMATHPRIMITIVE(LOG1P,log1p) -#endif -#ifdef HAVE_EXP2 + +MAKEMATHPRIMITIVE(EXP,exp) MAKEMATHPRIMITIVE(EXP2,exp2) -#endif -#ifdef HAVE_EXPM1 MAKEMATHPRIMITIVE(EXPM1,expm1) -#endif #ifdef HAVE_EXP10 MAKEMATHPRIMITIVE(EXP10,exp10) #endif + MAKEMATHPRIMITIVE(SQRT,sqrt) +MAKEMATHPRIMITIVE(CBRT,cbrt) MAKEMATHPRIMITIVE(RINT,rint) MAKEMATHPRIMITIVE(FLOOR,floor) MAKEMATHPRIMITIVE(CEIL,ceil) @@ -426,6 +427,10 @@ MAKEMATHPRIMITIVE(ABS,fabs) MAKEMATHPRIMITIVE2(ATAN2,atan2) MAKEMATHPRIMITIVE2(HYPOT,hypot) +MAKEMATHPRIMITIVE(ERF,erf) +MAKEMATHPRIMITIVE(GAMMA,tgamma) + + static Obj FuncSIGN_MACFLOAT(Obj self, Obj f) { Double vf = VAL_MACFLOAT(f); @@ -529,6 +534,7 @@ static StructBagNames BagNames[] = { static StructGVarFunc GVarFuncs [] = { GVAR_FUNC_1ARGS(MACFLOAT_INT, int), GVAR_FUNC_1ARGS(MACFLOAT_STRING, string), + GVAR_FUNC_1ARGS(SIN_MACFLOAT, macfloat), GVAR_FUNC_1ARGS(COS_MACFLOAT, macfloat), GVAR_FUNC_1ARGS(TAN_MACFLOAT, macfloat), @@ -536,25 +542,24 @@ static StructGVarFunc GVarFuncs [] = { GVAR_FUNC_1ARGS(ACOS_MACFLOAT, macfloat), GVAR_FUNC_1ARGS(ATAN_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(SINH_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(COSH_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(TANH_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(ASINH_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(ACOSH_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(ATANH_MACFLOAT, macfloat), + GVAR_FUNC_2ARGS(ATAN2_MACFLOAT, real, imag), GVAR_FUNC_2ARGS(HYPOT_MACFLOAT, real, imag), + GVAR_FUNC_1ARGS(LOG_MACFLOAT, macfloat), - GVAR_FUNC_1ARGS(EXP_MACFLOAT, macfloat), -#ifdef HAVE_LOG2 GVAR_FUNC_1ARGS(LOG2_MACFLOAT, macfloat), -#endif -#ifdef HAVE_LOG10 GVAR_FUNC_1ARGS(LOG10_MACFLOAT, macfloat), -#endif -#ifdef HAVE_LOG1P GVAR_FUNC_1ARGS(LOG1P_MACFLOAT, macfloat), -#endif -#ifdef HAVE_EXP2 + + GVAR_FUNC_1ARGS(EXP_MACFLOAT, macfloat), GVAR_FUNC_1ARGS(EXP2_MACFLOAT, macfloat), -#endif -#ifdef HAVE_EXPM1 GVAR_FUNC_1ARGS(EXPM1_MACFLOAT, macfloat), -#endif #ifdef HAVE_EXP10 GVAR_FUNC_1ARGS(EXP10_MACFLOAT, macfloat), #endif @@ -562,6 +567,11 @@ static StructGVarFunc GVarFuncs [] = { GVAR_FUNC_2ARGS(LDEXP_MACFLOAT, macfloat, int), GVAR_FUNC_1ARGS(FREXP_MACFLOAT, macfloat), GVAR_FUNC_1ARGS(SQRT_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(CBRT_MACFLOAT, macfloat), + + GVAR_FUNC_1ARGS(ERF_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(GAMMA_MACFLOAT, macfloat), + GVAR_FUNC_1ARGS(RINT_MACFLOAT, macfloat), GVAR_FUNC_1ARGS(INTFLOOR_MACFLOAT, macfloat), GVAR_FUNC_1ARGS(FLOOR_MACFLOAT, macfloat), diff --git a/tst/testinstall/float.tst b/tst/testinstall/float.tst index 821dc658bf..81166648aa 100644 --- a/tst/testinstall/float.tst +++ b/tst/testinstall/float.tst @@ -628,20 +628,79 @@ gap> Sin(0.); 0. gap> Tan(0.); 0. +gap> Sec(0.); +1. +gap> Csc(0.); +inf +gap> Cot(0.); +inf gap> Acos(1.); 0. gap> Asin(0.); 0. +gap> Atan(0.); +0. + +# +gap> Cosh(0.); +1. +gap> Sinh(0.); +0. +gap> Tanh(0.); +0. +gap> Sech(0.); +1. +gap> Csch(0.); +inf +gap> Coth(0.); +inf +gap> Asinh(0.); +0. +gap> Acosh(0.); +nan +gap> Atanh(0.); +0. + +# gap> Log(1.); 0. +gap> Log2(1.); +0. +gap> Log10(1.); +0. +gap> Log1p(0.); +0. + +# gap> Exp(0.); 1. -gap> if IsBound(Log2) then Assert(0, Log2(1.) = 0.); fi; -gap> if IsBound(Log10) then Assert(0, Log10(1.) = 0.); fi; -gap> if IsBound(Log1p) then Assert(0, Log1p(0.) = 0.); fi; -gap> if IsBound(Exp2) then Assert(0, Exp2(0.) = 1.); fi; -gap> if IsBound(Exp10) then Assert(0, Exp10(0.) = 1.); fi; -gap> if IsBound(Expm1) then Assert(0, Expm1(0.) = 0.); fi; +gap> Exp2(0.); +1. +gap> Exp10(0.); +1. +gap> Expm1(0.); +0. + +# +gap> CubeRoot(0.); +0. +gap> Square(0.); +0. + +# +gap> FrExp(0.); +[ 0., 0 ] +gap> LdExp(0.,0); +0. +gap> Norm(0.); +0. +gap> SinCos(0.); +[ 0., 1. ] +gap> Erf(0.); +0. +gap> #Zeta(0.); # TODO: not implemented for machine floats +gap> Gamma(1.); +1. # gap> Round(1.3); @@ -673,6 +732,26 @@ gap> Ceil(-1.9); gap> Ceil(-1.3); -1. +# +gap> Trunc(1.3); +1. +gap> Trunc(1.9); +1. +gap> Trunc(-1.9); +-1. +gap> Trunc(-1.3); +-1. + +# +gap> Frac(1.3); +0.3 +gap> Frac(1.9); +0.9 +gap> Frac(-1.9); +0.1 +gap> Frac(-1.3); +0.7 + # gap> AbsoluteValue(1.3); 1.3