Index: configure =================================================================== --- configure (revision 59523) +++ configure (working copy) @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 59484 . +# From configure.in Revision: 59533 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 2.6. # @@ -20368,6 +20368,9 @@ fi +# ************************************ +# * Check for mathematical functions * +# ************************************ # check for hypot() in math library LIBS_SAVE=$LIBS LIBS="$LIBS $LIBM" @@ -20473,6 +20476,122 @@ done + + + + + + + + + + + + + + + + + + + + +for ac_func in asinh atanh acosh cbrt copysign erf erfc expm1 \ + isfinite isnan isinf \ + j0 j1 jn lgamma_r log1p y0 y1 yn +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS=$LIBS_SAVE # check for wchar.h Index: configure.in =================================================================== --- configure.in (revision 59523) +++ configure.in (working copy) @@ -2974,10 +2974,18 @@ fi], [AC_MSG_RESULT(default LIBC="$LIBC")]) +# ************************************ +# * Check for mathematical functions * +# ************************************ # check for hypot() in math library LIBS_SAVE=$LIBS LIBS="$LIBS $LIBM" AC_REPLACE_FUNCS(hypot) + +AC_CHECK_FUNCS(asinh atanh acosh cbrt copysign erf erfc expm1 \ + isfinite isnan isinf \ + j0 j1 jn lgamma_r log1p y0 y1 yn) + LIBS=$LIBS_SAVE # check for wchar.h Index: Include/pyport.h =================================================================== --- Include/pyport.h (revision 59523) +++ Include/pyport.h (working copy) @@ -349,6 +349,17 @@ #define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) (NARROW)(VALUE) #endif +/* High precision defintion of pi and e (Euler) + * The values are taken from libc6's math.h. + */ +#ifndef Py_MATH_PI +#define Py_MATH_PI 3.1415926535897932384626433832795029L +#endif + +#ifndef Py_MATH_E +#define Py_MATH_E 2.7182818284590452353602874713526625L +#endif + /* Py_IS_NAN(X) * Return 1 if float or double arg is a NaN, else 0. * Caution: @@ -358,8 +369,12 @@ * a platform where it doesn't work. */ #ifndef Py_IS_NAN +#ifdef HAVE_ISNAN +#define Py_IS_NAN(X) isnan(X) +#else #define Py_IS_NAN(X) ((X) != (X)) #endif +#endif /* Py_IS_INFINITY(X) * Return 1 if float or double arg is an infinity, else 0. @@ -370,8 +385,12 @@ * Override in pyconfig.h if you have a better spelling on your platform. */ #ifndef Py_IS_INFINITY +#ifdef HAVE_ISINF +#define Py_IS_INFINITY(X) isinf(X) +#else #define Py_IS_INFINITY(X) ((X) && (X)*0.5 == (X)) #endif +#endif /* Py_IS_FINITE(X) * Return 1 if float or double arg is neither infinite nor NAN, else 0. @@ -379,8 +398,12 @@ * macro for this particular test is useful */ #ifndef Py_IS_FINITE +#ifdef HAVE_ISFINITE +#define Py_IS_FINITE(X) isfinite +#else #define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X)) #endif +#endif /* HUGE_VAL is supposed to expand to a positive double infinity. Python * uses Py_HUGE_VAL instead because some platforms are broken in this @@ -393,6 +416,15 @@ #define Py_HUGE_VAL HUGE_VAL #endif +/* Py_NAN + * A value that evaluates to a NaN. On IEEE 754 platforms INF*0 or + * INF/INF works. Define Py_NO_NAN in pyconfig.h if your platform + * doesn't support NaNs. + */ +#if !defined(Py_NAN) && !defined(Py_NO_NAN) +#define Py_NAN (Py_HUGE_VAL * 0.) +#endif + /* Py_OVERFLOWED(X) * Return 1 iff a libm function overflowed. Set errno to 0 before calling * a libm function, and invoke this macro after, passing the function Index: Include/pystrcmp.h =================================================================== --- Include/pystrcmp.h (revision 0) +++ Include/pystrcmp.h (revision 0) @@ -0,0 +1,23 @@ +#ifndef Py_STRCMP_H +#define Py_STRCMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(int) PyOS_mystrnicmp(const char *, const char *, Py_ssize_t); +PyAPI_FUNC(int) PyOS_mystricmp(const char *, const char *); + +#ifdef MS_WINDOWS +#define PyOS_strnicmp strnicmp +#define PyOS_stricmp stricmp +#else +#define PyOS_strnicmp PyOS_mystrnicmp +#define PyOS_stricmp PyOS_mystricmp +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_STRCMP_H */ Property changes on: Include\pystrcmp.h ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: Include/Python.h =================================================================== --- Include/Python.h (revision 59523) +++ Include/Python.h (working copy) @@ -129,6 +129,7 @@ #include "eval.h" #include "pystrtod.h" +#include "pystrcmp.h" /* _Py_Mangle is defined in compile.c */ PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); Index: Lib/test/test_float.py =================================================================== --- Lib/test/test_float.py (revision 59523) +++ Lib/test/test_float.py (working copy) @@ -3,6 +3,12 @@ import os from test import test_support +def isinf(x): + return x * 0.5 == x + +def isnan(x): + return x != x + class FormatFunctionsTestCase(unittest.TestCase): def setUp(self): @@ -128,13 +134,78 @@ self.assertEqual(v, eval(repr(v))) floats_file.close() +# Beginning with Python 2.6 float has cross platform compatible +# ways to create and representate inf and nan +class InfNanTest(unittest.TestCase): + def test_inf_from_str(self): + self.assert_(isinf(float("inf"))) + self.assert_(isinf(float("+inf"))) + self.assert_(isinf(float("-inf"))) + self.assertEqual(repr(float("inf")), "inf") + self.assertEqual(repr(float("+inf")), "inf") + self.assertEqual(repr(float("-inf")), "-inf") + + self.assertEqual(repr(float("INF")), "inf") + self.assertEqual(repr(float("+Inf")), "inf") + self.assertEqual(repr(float("-iNF")), "-inf") + + self.assertEqual(str(float("inf")), "inf") + self.assertEqual(str(float("+inf")), "inf") + self.assertEqual(str(float("-inf")), "-inf") + + self.assertRaises(ValueError, float, "info") + self.assertRaises(ValueError, float, "+info") + self.assertRaises(ValueError, float, "-info") + self.assertRaises(ValueError, float, "in") + self.assertRaises(ValueError, float, "+in") + self.assertRaises(ValueError, float, "-in") + + def test_inf_as_str(self): + self.assertEqual(repr(1e300 * 1e300), "inf") + self.assertEqual(repr(-1e300 * 1e300), "-inf") + + self.assertEqual(str(1e300 * 1e300), "inf") + self.assertEqual(str(-1e300 * 1e300), "-inf") + + def test_nan_from_str(self): + self.assert_(isnan(float("nan"))) + self.assert_(isnan(float("+nan"))) + self.assert_(isnan(float("-nan"))) + + self.assertEqual(repr(float("nan")), "nan") + self.assertEqual(repr(float("+nan")), "nan") + self.assertEqual(repr(float("-nan")), "nan") + + self.assertEqual(repr(float("NAN")), "nan") + self.assertEqual(repr(float("+NAn")), "nan") + self.assertEqual(repr(float("-NaN")), "nan") + + self.assertEqual(str(float("nan")), "nan") + self.assertEqual(str(float("+nan")), "nan") + self.assertEqual(str(float("-nan")), "nan") + + self.assertRaises(ValueError, float, "nana") + self.assertRaises(ValueError, float, "+nana") + self.assertRaises(ValueError, float, "-nana") + self.assertRaises(ValueError, float, "na") + self.assertRaises(ValueError, float, "+na") + self.assertRaises(ValueError, float, "-na") + + def test_nan_as_str(self): + self.assertEqual(repr(1e300 * 1e300 * 0), "nan") + self.assertEqual(repr(-1e300 * 1e300 * 0), "nan") + + self.assertEqual(str(1e300 * 1e300 * 0), "nan") + self.assertEqual(str(-1e300 * 1e300 * 0), "nan") + def test_main(): test_support.run_unittest( FormatFunctionsTestCase, UnknownFormatTestCase, IEEEFormatTestCase, - #ReprTestCase + ReprTestCase, + InfNanTest, ) if __name__ == '__main__': Index: Lib/test/test_math.py =================================================================== --- Lib/test/test_math.py (revision 59523) +++ Lib/test/test_math.py (working copy) @@ -10,6 +10,12 @@ class MathTests(unittest.TestCase): + def available(self, name): + if not hasattr(math, name): + if verbose: + print "math.%s is not available" % name + return False + def ftest(self, name, value, expected): if abs(value-expected) > eps: # Use %r instead of %f so the error message @@ -29,12 +35,18 @@ self.ftest('acos(0)', math.acos(0), math.pi/2) self.ftest('acos(1)', math.acos(1), 0) + def testAcosh(self): + self.assertRaises(TypeError, math.acosh) + def testAsin(self): self.assertRaises(TypeError, math.asin) self.ftest('asin(-1)', math.asin(-1), -math.pi/2) self.ftest('asin(0)', math.asin(0), 0) self.ftest('asin(1)', math.asin(1), math.pi/2) + def testAsinh(self): + self.assertRaises(TypeError, math.asinh) + def testAtan(self): self.assertRaises(TypeError, math.atan) self.ftest('atan(-1)', math.atan(-1), -math.pi/4) @@ -49,6 +61,14 @@ self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4) self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2) + def testAtanh(self): + self.assertRaises(TypeError, math.atanh) + + def testAcosh(self): + self.assertRaises(TypeError, math.cbrt) + self.ftest('cbrt(27)', math.cbrt(0.), 0.) + self.ftest('cbrt(27)', math.cbrt(27.), 3.) + def testCeil(self): self.assertRaises(TypeError, math.ceil) self.ftest('ceil(0.5)', math.ceil(0.5), 1) @@ -82,6 +102,9 @@ self.ftest('exp(0)', math.exp(0), 1) self.ftest('exp(1)', math.exp(1), math.e) + def testExpm1(self): + self.assertRaises(TypeError, math.expm1) + def testFabs(self): self.assertRaises(TypeError, math.fabs) self.ftest('fabs(-1)', math.fabs(-1), 1) @@ -150,6 +173,9 @@ self.ftest('log10(1)', math.log10(1), 0) self.ftest('log10(10)', math.log10(10), 1) + def testLog1p(self): + self.assertRaises(TypeError, math.log1p) + def testModf(self): self.assertRaises(TypeError, math.modf) @@ -203,6 +229,82 @@ self.ftest('tanh(0)', math.tanh(0), 0) self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0) + def testBessel_first(self): + if not self.available("j0"): + return + for z in 2.4048255576957727, 5.5200781102863106, 8.6537279129110122: + self.assertAlmostEqual(math.j0(z), 0) + self.assertAlmostEqual(math.jn(0, z), 0) + self.assertAlmostEqual(math.j0(0.), 1) + self.assert_(math.j0(4.) < 0) + for z in 3.8317059702075123, 7.0155866698156122, 10.173468135062722: + self.assertAlmostEqual(math.j1(z), 0) + self.assertAlmostEqual(math.jn(1, z), 0) + self.assert_(math.j1(1.) > 0) + self.assert_(math.j0(5.5) < 0) + for z in 5.1356223018406826, 8.4172441403998629, 11.619841172149059: + self.assertAlmostEqual(math.jn(2, z), 0) + self.assert_(math.jn(2 ,1.) > 0) + self.assert_(math.jn(2, 7.) < 0) + + def testBessel_second(self): + if not self.available("y0"): + return + for z in 0.89357696627916752, 3.9576784193148579, 7.0860510603017727: + self.assertAlmostEqual(math.y0(z), 0) + self.assertAlmostEqual(math.yn(0, z), 0) + for z in 2.1971413260310170, 5.4296810407941351, 8.5960058683311689: + self.assertAlmostEqual(math.y1(z), 0) + self.assertAlmostEqual(math.yn(1, z), 0) + for z in 3.3842417671495935, 6.7938075132682675, 10.023477979360038: + self.assertAlmostEqual(math.yn(2, z), 0) + + def testLgamma(self): + if not self.available("lgamma"): + return + self.assertEqual(math.lgamma(1.), (0.0, 1)) + gamma, sign = math.lgamma(1.2) + self.assertAlmostEqual(gamma, -0.0853740900) + self.assertEqual(sign, 1) + self.assertRaises(ValueError, math.lgamma, 0.) + + def testErf(self): + if not self.available("erf"): + return + self.assertEqual(math.erf(0.), 0.) + self.assertAlmostEqual(math.erf(6.), 1.) + + def testErfc(self): + if not self.available("erfc"): + return + self.assertEqual(math.erfc(0.), 1.) + self.assertAlmostEqual(math.erfc(10.), 0.) + + def testSign(self): + self.assertEqual(math.sign(0), 0) + self.assertEqual(math.sign(-2), -1) + self.assertEqual(math.sign(+2), 1) + self.assertEqual(math.sign(0.), 1) + self.assertEqual(math.sign(-0.), -1) + self.assertEqual(math.sign(-2.), -1) + self.assertEqual(math.sign(+2.), 1) + + def testIsnan(self): + self.assert_(math.isnan(float("nan"))) + self.assert_(math.isnan(float("inf")* 0.)) + self.failIf(math.isnan(float("inf"))) + self.failIf(math.isnan(0.)) + self.failIf(math.isnan(1.)) + + def testIsinf(self): + self.assert_(math.isinf(float("inf"))) + self.assert_(math.isinf(float("-inf"))) + self.assert_(math.isinf(1E400)) + self.assert_(math.isinf(-1E400)) + self.failIf(math.isinf(float("nan"))) + self.failIf(math.isinf(0.)) + self.failIf(math.isinf(1.)) + # RED_FLAG 16-Oct-2000 Tim # While 2.0 is more consistent about exceptions than previous releases, it # still fails this part of the test on some platforms. For now, we only @@ -247,3 +349,4 @@ if __name__ == '__main__': test_main() + Index: Makefile.pre.in =================================================================== --- Makefile.pre.in (revision 59523) +++ Makefile.pre.in (working copy) @@ -275,6 +275,7 @@ Python/sysmodule.o \ Python/traceback.o \ Python/getopt.o \ + Python/pystrcmp.o \ Python/pystrtod.o \ Python/$(DYNLOADFILE) \ $(LIBOBJS) \ @@ -554,6 +555,8 @@ Include/pymem.h \ Include/pyport.h \ Include/pystate.h \ + Include/pystrtod.h \ + Include/pystrcmp.h \ Include/pythonrun.h \ Include/rangeobject.h \ Include/setobject.h \ Index: Modules/mathmodule.c =================================================================== --- Modules/mathmodule.c (revision 59523) +++ Modules/mathmodule.c (working copy) @@ -2,6 +2,7 @@ #include "Python.h" #include "longintrepr.h" /* just for SHIFT */ +#include #ifndef _MSC_VER #ifndef __STDC__ @@ -86,6 +87,29 @@ return PyFloat_FromDouble(x); } +static PyObject * +math_2n(PyObject *args, double (*func) (int, double), char *funcname) +{ + PyObject *oi, *ox; + long i; + double x; + if (! PyArg_UnpackTuple(args, funcname, 2, 2, &oi, &ox)) + return NULL; + i = PyInt_AsLong(oi); + x = PyFloat_AsDouble(ox); + if ((i == -1 || x == -1.0) && PyErr_Occurred()) + return NULL; + errno = 0; + PyFPE_START_PROTECT("in math_2", return 0) + x = (*func)(i, x); + PyFPE_END_PROTECT(x) + Py_SET_ERRNO_ON_MATH_ERROR(x); + if (errno && is_error(x)) + return NULL; + else + return PyFloat_FromDouble(x); +} + #define FUNC1(funcname, func, docstring) \ static PyObject * math_##funcname(PyObject *self, PyObject *args) { \ return math_1(args, func); \ @@ -97,7 +121,49 @@ return math_2(args, func, #funcname); \ }\ PyDoc_STRVAR(math_##funcname##_doc, docstring); +#define FUNC2n(funcname, func, docstring) \ + static PyObject * math_##funcname(PyObject *self, PyObject *args) { \ + return math_2n(args, func, #funcname); \ + }\ + PyDoc_STRVAR(math_##funcname##_doc, docstring); +#ifndef HAVE_ACOSH +double acosh(double x) +{ + return 2.*log(sqrt((x+1.)/2.) + sqrt((x-1.)/2.)); +} +#endif +#ifndef HAVE_ASINH +double asinh(double x) +{ + return log(x + sqrt(1.+(x*x))); +} +#endif +#ifndef HAVE_ATANH +double atanh(double x) +{ + return (log(1.+x) - log(1.-x))/2.; +} +#endif +#ifndef HAVE_LOG1P +double log1p(double x) +{ + return log(1. + x); +} +#endif +#ifndef HAVE_EXPM1 +double expm1(double x) +{ + return exp(x) - 1.; +} +#endif +#ifndef HAVE_CBRT +double cbrt(double x) +{ + return pow(x, 1./3.); +} +#endif + FUNC1(acos, acos, "acos(x)\n\nReturn the arc cosine (measured in radians) of x.") FUNC1(asin, asin, @@ -107,6 +173,14 @@ FUNC2(atan2, atan2, "atan2(y, x)\n\nReturn the arc tangent (measured in radians) of y/x.\n" "Unlike atan(y/x), the signs of both x and y are considered.") +FUNC1(acosh, acosh, + "acosh(x)\n\nReturn the arc hyperbolic cosine (measured in radians) of x.") +FUNC1(asinh, asinh, + "asin(x)\n\nReturn the arc hyperbolic sine (measured in radians) of x.") +FUNC1(atanh, atanh, + "atan(x)\n\nReturn the arc hyperbolic tangent (measured in radians) of x.") +FUNC1(cbrt, cbrt, + "cbrt(x)\n\nReturn the cube root of x (x^(1/3)).") FUNC1(ceil, ceil, "ceil(x)\n\nReturn the ceiling of x as a float.\n" "This is the smallest integral value >= x.") @@ -114,8 +188,19 @@ "cos(x)\n\nReturn the cosine of x (measured in radians).") FUNC1(cosh, cosh, "cosh(x)\n\nReturn the hyperbolic cosine of x.") +#ifdef HAVE_ERF +FUNC1(erf, erf, + "erf(x)\n\nReturn the error function of x.") +#endif +#ifdef HAVE_ERFC +FUNC1(erfc, erfc, + "erfc(x)\n\nReturn the error function of 1-erf(x) in a way that \n\ +avoids rounding errors for large x.") +#endif FUNC1(exp, exp, "exp(x)\n\nReturn e raised to the power of x.") +FUNC1(expm1, expm1, + "expm1(x)\n\nReturn one less e raised to the power of x, exp(x)-1.") FUNC1(fabs, fabs, "fabs(x)\n\nReturn the absolute value of the float x.") FUNC1(floor, floor, @@ -126,6 +211,18 @@ " x % y may differ.") FUNC2(hypot, hypot, "hypot(x,y)\n\nReturn the Euclidean distance, sqrt(x*x + y*y).") +#ifdef HAVE_J0 +FUNC1(j0, j0, + "j0(x)\n\nReturn Bessel functions of x of the 1st kind of order 0.") +#endif +#ifdef HAVE_J1 +FUNC1(j1, j1, + "j1(x)\n\nReturn Bessel functions of x of the 1st kind of order 1.") +#endif +#ifdef HAVE_JN +FUNC2n(jn, jn, + "jn(n, x)\n\nReturn Bessel functions of x of the 1st kind of order n.") +#endif FUNC2(pow, pow, "pow(x,y)\n\nReturn x**y (x to the power of y).") FUNC1(sin, sin, @@ -138,6 +235,18 @@ "tan(x)\n\nReturn the tangent of x (measured in radians).") FUNC1(tanh, tanh, "tanh(x)\n\nReturn the hyperbolic tangent of x.") +#ifdef HAVE_Y0 +FUNC1(y0, y0, + "j0(x)\n\nReturn Bessel functions of x of the 2nd kind of order 0.") +#endif +#ifdef HAVE_Y1 +FUNC1(y1, y1, + "j1(x)\n\nReturn Bessel functions of x of the 2nd kind of order 1.") +#endif +#ifdef HAVE_YN +FUNC2n(yn, yn, + "jn(n, x)\n\nReturn Bessel functions of x of the 2nd kind of order n.") +#endif static PyObject * math_frexp(PyObject *self, PyObject *arg) @@ -274,20 +383,29 @@ return loghelper(arg, log10, "log10"); } + PyDoc_STRVAR(math_log10_doc, "log10(x) -> the base 10 logarithm of x."); -/* XXX(nnorwitz): Should we use the platform M_PI or something more accurate - like: 3.14159265358979323846264338327950288 */ -static const double degToRad = 3.141592653589793238462643383 / 180.0; +static PyObject * +math_log1p(PyObject *self, PyObject *arg) +{ + return loghelper(arg, log1p, "log1p"); +} +PyDoc_STRVAR(math_log1p_doc, +"log1p(x) -> the natural logarithm (base e) of 1 + x."); + +static const double degToRad = Py_MATH_PI / 180.0; +static const double radToDeg = 180.0 / Py_MATH_PI; + static PyObject * math_degrees(PyObject *self, PyObject *arg) { double x = PyFloat_AsDouble(arg); if (x == -1.0 && PyErr_Occurred()) return NULL; - return PyFloat_FromDouble(x / degToRad); + return PyFloat_FromDouble(x * radToDeg); } PyDoc_STRVAR(math_degrees_doc, @@ -305,32 +423,174 @@ PyDoc_STRVAR(math_radians_doc, "radians(x) -> converts angle x from degrees to radians"); +static PyObject * +math_isnan(PyObject *self, PyObject *arg) +{ + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + return PyBool_FromLong((long)Py_IS_NAN(x)); +} + +PyDoc_STRVAR(math_isnan_doc, +"isnan(x) -> bool\n\ +Checks if float x is not a number (NaN)"); + +static PyObject * +math_isinf(PyObject *self, PyObject *arg) +{ + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + return PyBool_FromLong((long)Py_IS_INFINITY(x)); +} + +PyDoc_STRVAR(math_isinf_doc, +"isinf(x) -> bool\n\ +Checks if float x is infinite (positive or negative)"); + +static PyObject * +math_sign(PyObject *self, PyObject *arg) +{ + int result = -2; + if (PyInt_Check(arg)) { + long l = PyInt_AsLong(arg); + if (l == -1.0 && PyErr_Occurred()) + return NULL; + result = l > 0 ? 1 : + l < 0 ? -1 : 0; + + } + if (PyLong_Check(arg)) { + result = _PyLong_Sign(arg); + } + else if (PyFloat_Check(arg)) { + double x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) + return NULL; +#ifdef HAVE_COPYSIGN + result = (int)copysign(1., x); +#elif defined(MS_WINDOWS) + result = (int)_copysign(1., x); +#else + result = x > 0. ? 1 : + x < 0. ? -1 : 0; +#endif + } + if (result == -2) { + PyErr_Format(PyExc_TypeError, + "sign() expected int, long or float, found %s", + Py_Type(arg)->tp_name); + return NULL; + } + return PyInt_FromLong((long)result); +} + +PyDoc_STRVAR(math_sign_doc, +"sign(x) -> +1 / 0 / -1\n\ +Return the sign of an int, long or float. On platforms with full IEEE 754\n\ +semantic sign(0.) returns +1 and sign(-0.) returns -1. On other platforms\n\ +sign(0.) always returns 0."); + +#ifdef HAVE_LGAMMA_R +static PyObject * +math_lgamma(PyObject *self, PyObject *arg) +{ + PyObject *result, *o; + double x; + int sign; + + x = PyFloat_AsDouble(arg); + if (x == -1.0 && PyErr_Occurred()) + return NULL; + errno = 0; + PyFPE_START_PROTECT("in lgamma", return NULL) + x = lgamma_r(x, &sign); + PyFPE_END_PROTECT(x) + Py_SET_ERRNO_ON_MATH_ERROR(x); + if (errno && is_error(x)) + return NULL; + + result = PyTuple_New(2); + if (result == NULL) + return NULL; + o = PyFloat_FromDouble(x); + if (PyTuple_SetItem(result, 0, o) != 0) + return NULL; + o = PyInt_FromLong(sign); + if (PyTuple_SetItem(result, 1, o) != 0) + return NULL; + return result; + +} +PyDoc_STRVAR(math_lgamma_doc, +"lgamma(x) -> (result, sign)\n\ +Return the natural logarithm of the gamma function and the sign of the \n\ +gamma function so that gamma = exp(result) * sign."); +#endif /* HAVE_LGAMMA_R */ + static PyMethodDef math_methods[] = { {"acos", math_acos, METH_O, math_acos_doc}, {"asin", math_asin, METH_O, math_asin_doc}, {"atan", math_atan, METH_O, math_atan_doc}, {"atan2", math_atan2, METH_VARARGS, math_atan2_doc}, + {"acosh", math_acosh, METH_O, math_acosh_doc}, + {"asinh", math_asinh, METH_O, math_asinh_doc}, + {"atanh", math_atanh, METH_O, math_atanh_doc}, + {"cbrt", math_cbrt, METH_O, math_cbrt_doc}, {"ceil", math_ceil, METH_O, math_ceil_doc}, {"cos", math_cos, METH_O, math_cos_doc}, {"cosh", math_cosh, METH_O, math_cosh_doc}, {"degrees", math_degrees, METH_O, math_degrees_doc}, +#ifdef HAVE_ERF + {"erf", math_erf, METH_O, math_erf_doc}, +#endif +#ifdef HAVE_ERFC + {"erfc", math_erfc, METH_O, math_erfc_doc}, +#endif {"exp", math_exp, METH_O, math_exp_doc}, + {"expm1", math_expm1, METH_O, math_expm1_doc}, {"fabs", math_fabs, METH_O, math_fabs_doc}, {"floor", math_floor, METH_O, math_floor_doc}, {"fmod", math_fmod, METH_VARARGS, math_fmod_doc}, {"frexp", math_frexp, METH_O, math_frexp_doc}, {"hypot", math_hypot, METH_VARARGS, math_hypot_doc}, + {"isinf", math_isinf, METH_O, math_isinf_doc}, + {"isnan", math_isnan, METH_O, math_isnan_doc}, {"ldexp", math_ldexp, METH_VARARGS, math_ldexp_doc}, +#ifdef HAVE_LGAMMA_R + {"lgamma", math_lgamma, METH_O, math_lgamma_doc}, +#endif {"log", math_log, METH_VARARGS, math_log_doc}, + {"log1p", math_log1p, METH_O, math_log1p_doc}, {"log10", math_log10, METH_O, math_log10_doc}, {"modf", math_modf, METH_O, math_modf_doc}, {"pow", math_pow, METH_VARARGS, math_pow_doc}, {"radians", math_radians, METH_O, math_radians_doc}, + {"sign", math_sign, METH_O, math_sign_doc}, {"sin", math_sin, METH_O, math_sin_doc}, {"sinh", math_sinh, METH_O, math_sinh_doc}, {"sqrt", math_sqrt, METH_O, math_sqrt_doc}, {"tan", math_tan, METH_O, math_tan_doc}, {"tanh", math_tanh, METH_O, math_tanh_doc}, +#ifdef HAVE_J0 + {"j0", math_j0, METH_O, math_j0_doc}, +#endif +#ifdef HAVE_J1 + {"j1", math_j1, METH_O, math_j1_doc}, +#endif +#ifdef HAVE_JN + {"jn", math_jn, METH_VARARGS, math_jn_doc}, +#endif +#ifdef HAVE_Y0 + {"y0", math_y0, METH_O, math_y0_doc}, +#endif +#ifdef HAVE_Y1 + {"y1", math_y1, METH_O, math_y1_doc}, +#endif +#ifdef HAVE_YN + {"yn", math_yn, METH_VARARGS, math_yn_doc}, +#endif {NULL, NULL} /* sentinel */ }; @@ -351,13 +611,13 @@ if (d == NULL) goto finally; - if (!(v = PyFloat_FromDouble(atan(1.0) * 4.0))) + if (!(v = PyFloat_FromDouble(Py_MATH_PI))) goto finally; if (PyDict_SetItemString(d, "pi", v) < 0) goto finally; Py_DECREF(v); - if (!(v = PyFloat_FromDouble(exp(1.0)))) + if (!(v = PyFloat_FromDouble(Py_MATH_E))) goto finally; if (PyDict_SetItemString(d, "e", v) < 0) goto finally; Index: Objects/floatobject.c =================================================================== --- Objects/floatobject.c (revision 59545) +++ Objects/floatobject.c (working copy) @@ -128,7 +128,7 @@ PyObject * PyFloat_FromString(PyObject *v, char **pend) { - const char *s, *last, *end; + const char *s, *last, *end, *sp; double x; char buffer[256]; /* for errors */ #ifdef Py_USING_UNICODE @@ -171,6 +171,7 @@ PyErr_SetString(PyExc_ValueError, "empty string for float()"); return NULL; } + sp = s; /* We don't care about overflow or underflow. If the platform supports * them, infinities and signed zeroes (on underflow) are fine. * However, strtod can return 0 for denormalized numbers, where atof @@ -187,6 +188,24 @@ if (end > last) end = last; if (end == s) { + char *p = (char*)sp; + int sign = 1; + + if (*p == '-') { + sign = -1; + p++; + } + if (*p == '+') { + p++; + } + if (PyOS_strnicmp(p, "inf", 4) == 0) { + return PyFloat_FromDouble(sign * HUGE_VAL); + } +#ifdef Py_NAN + if(PyOS_strnicmp(p, "nan", 4) == 0) { + return PyFloat_FromDouble(Py_NAN); + } +#endif PyOS_snprintf(buffer, sizeof(buffer), "invalid literal for float(): %.200s", s); PyErr_SetString(PyExc_ValueError, buffer); @@ -271,6 +290,7 @@ { register char *cp; char format[32]; + int i; /* Subroutine for float_repr and float_print. We want float numbers to be recognizable as such, i.e., they should contain a decimal point or an exponent. @@ -293,7 +313,32 @@ *cp++ = '.'; *cp++ = '0'; *cp++ = '\0'; + return; } + /* checking the next three items should be more than enough to + * detect inf or nan, even on Windows. We check for inf or nan + * at last because they are rare cases. + */ + for (i=0; *cp != '\0' && i<3; cp++, i++) { + if (isdigit(Py_CHARMASK(*cp)) || *cp == '.') + continue; + /* found something that is neither a digit nor point + * it might be a NaN or INF + */ +#ifdef Py_NAN + if (Py_IS_NAN(v->ob_fval)) { + strcpy(buf , "nan"); + } + else +#endif + if (Py_IS_INFINITY(v->ob_fval)) { + cp = buf; + if (*cp == '-') + cp++; + strcpy(cp, "inf"); + } + break; + } } /* XXX PyFloat_AsStringEx should not be a public API function (for one Index: PC/pyconfig.h =================================================================== --- PC/pyconfig.h (revision 59523) +++ PC/pyconfig.h (working copy) @@ -386,6 +386,60 @@ /* Fairly standard from here! */ +/* Define to 1 if you have the `acosh' function. */ +/* #define HAVE_ACOSH 1 */ + +/* Define to 1 if you have the `asinh' function. */ +/* #define HAVE_ASINH 1 */ + +/* Define to 1 if you have the `atanh' function. */ +/* #define HAVE_ATANH 1 */ + +/* Define to 1 if you have the `cbrt' function. */ +/* #define HAVE_CBRT 1 */ + +/* Define to 1 if you have the `copysign' function. */ +/* #define HAVE_COPYSIGN 1*/ + +/* Define to 1 if you have the `erf' function. */ +/* #define HAVE_ERF 1 */ + +/* Define to 1 if you have the `erfc' function. */ +/* #define HAVE_ERFC 1 */ + +/* Define to 1 if you have the `expm1' function. */ +/* #define HAVE_EXPM1 1 */ + +/* Define to 1 if you have the `lgamma_r' function. */ +/* #define HAVE_LGAMMA_R 1 */ + +/* Define to 1 if you have the `log1p' function. */ +/* #define HAVE_LOG1P 1 */ + +/* Define to 1 if you have the `isinf' function. */ +#define HAVE_ISINF 1 + +/* Define to 1 if you have the `isnan' function. */ +#define HAVE_ISNAN 1 + +/* Define to 1 if you have the `j0' function. */ +#define HAVE_J0 1 + +/* Define to 1 if you have the `j1' function. */ +#define HAVE_J1 1 + +/* Define to 1 if you have the `jn' function. */ +#define HAVE_JN 1 + +/* Define to 1 if you have the `y0' function. */ +#define HAVE_Y0 1 + +/* Define to 1 if you have the `y1' function. */ +#define HAVE_Y1 1 + +/* Define to 1 if you have the `yn' function. */ +#define HAVE_YN 1 + /* Define if on AIX 3. System headers sometimes define this. We just want to avoid a redefinition error message. */ Index: PCbuild8/pythoncore/pythoncore.vcproj =================================================================== --- PCbuild8/pythoncore/pythoncore.vcproj (revision 59523) +++ PCbuild8/pythoncore/pythoncore.vcproj (working copy) @@ -736,6 +736,10 @@ > + + @@ -1194,6 +1198,10 @@ > + + Index: PCbuild9/pythoncore.vcproj =================================================================== --- PCbuild9/pythoncore.vcproj (revision 59523) +++ PCbuild9/pythoncore.vcproj (working copy) @@ -875,6 +875,10 @@ > + + @@ -1715,6 +1719,10 @@ > + + Index: PCbuild/pythoncore.vcproj =================================================================== --- PCbuild/pythoncore.vcproj (revision 59523) +++ PCbuild/pythoncore.vcproj (working copy) @@ -701,6 +701,10 @@ RelativePath="..\Python\pystate.c"> + + header file. */ #undef HAVE_ASM_TYPES_H +/* Define to 1 if you have the `atanh' function. */ +#undef HAVE_ATANH + /* Define if GCC supports __attribute__((format(PyArg_ParseTuple, 2, 3))) */ #undef HAVE_ATTRIBUTE_FORMAT_PARSETUPLE @@ -67,6 +76,9 @@ /* Define this if you have the type _Bool. */ #undef HAVE_C99_BOOL +/* Define to 1 if you have the `cbrt' function. */ +#undef HAVE_CBRT + /* Define to 1 if you have the `chflags' function. */ #undef HAVE_CHFLAGS @@ -85,6 +97,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CONIO_H +/* Define to 1 if you have the `copysign' function. */ +#undef HAVE_COPYSIGN + /* Define to 1 if you have the `ctermid' function. */ #undef HAVE_CTERMID @@ -135,12 +150,21 @@ /* Defined when any dynamic module loading is enabled. */ #undef HAVE_DYNAMIC_LOADING +/* Define to 1 if you have the `erf' function. */ +#undef HAVE_ERF + +/* Define to 1 if you have the `erfc' function. */ +#undef HAVE_ERFC + /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the `execv' function. */ #undef HAVE_EXECV +/* Define to 1 if you have the `expm1' function. */ +#undef HAVE_EXPM1 + /* Define if you have the 'fchdir' function. */ #undef HAVE_FCHDIR @@ -288,6 +312,24 @@ /* Define to 1 if you have the header file. */ #undef HAVE_IO_H +/* Define to 1 if you have the `isfinite' function. */ +#undef HAVE_ISFINITE + +/* Define to 1 if you have the `isinf' function. */ +#undef HAVE_ISINF + +/* Define to 1 if you have the `isnan' function. */ +#undef HAVE_ISNAN + +/* Define to 1 if you have the `j0' function. */ +#undef HAVE_J0 + +/* Define to 1 if you have the `j1' function. */ +#undef HAVE_J1 + +/* Define to 1 if you have the `jn' function. */ +#undef HAVE_JN + /* Define to 1 if you have the `kill' function. */ #undef HAVE_KILL @@ -312,6 +354,9 @@ /* Define to 1 if you have the `lchown' function. */ #undef HAVE_LCHOWN +/* Define to 1 if you have the `lgamma_r' function. */ +#undef HAVE_LGAMMA_R + /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL @@ -342,6 +387,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_NETLINK_H +/* Define to 1 if you have the `log1p' function. */ +#undef HAVE_LOG1P + /* Define this if you have the type long long. */ #undef HAVE_LONG_LONG @@ -747,6 +795,15 @@ */ #undef HAVE_WORKING_TZSET +/* Define to 1 if you have the `y0' function. */ +#undef HAVE_Y0 + +/* Define to 1 if you have the `y1' function. */ +#undef HAVE_Y1 + +/* Define to 1 if you have the `yn' function. */ +#undef HAVE_YN + /* Define if the zlib library has inflateCopy */ #undef HAVE_ZLIB_COPY @@ -1028,3 +1085,4 @@ #endif /*Py_PYCONFIG_H*/ + Index: Python/pystrcmp.c =================================================================== --- Python/pystrcmp.c (revision 0) +++ Python/pystrcmp.c (revision 0) @@ -0,0 +1,25 @@ +/* Cross platform case insenstive string compare functions + */ + +#include "Python.h" + +int +PyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size) +{ + if (size == 0) + return 0; + while ((--size > 0) && (tolower(*s1) == tolower(*s2))) { + if (!*s1++ || !*s2++) + break; + } + return tolower(*s1) - tolower(*s2); +} + +int +PyOS_mystricmp(const char *s1, const char *s2) +{ + while (*s1 && (tolower(*s1++) == tolower(*s2++))) { + ; + } + return (tolower(*s1) - tolower(*s2)); +} Property changes on: Python\pystrcmp.c ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native