Author: Matti Picus <matti.pi...@gmail.com> Branch: py3.5 Changeset: r93685:6742308b0f34 Date: 2018-01-19 14:45 +0200 http://bitbucket.org/pypy/pypy/changeset/6742308b0f34/
Log: merge default into py3.5 diff too long, truncating to 2000 out of 2456 lines diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -10,3 +10,7 @@ Big refactoring of some cpyext code, which avoids a lot of nonsense when calling C from Python and vice-versa: the result is a big speedup in function/method calls, up to 6 times faster. + +.. branch: cpyext-datetime2 + +Support ``tzinfo`` field on C-API datetime objects, fixes latest pandas HEAD diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py --- a/pypy/interpreter/astcompiler/assemble.py +++ b/pypy/interpreter/astcompiler/assemble.py @@ -1,7 +1,7 @@ """Python control flow graph generation and bytecode assembly.""" +import math import os -from rpython.rlib import rfloat from rpython.rlib.objectmodel import specialize, we_are_translated from pypy.interpreter.astcompiler import ast, consts, misc, symtable @@ -269,7 +269,7 @@ w_type = space.type(obj) if space.is_w(w_type, space.w_float): val = space.float_w(obj) - if val == 0.0 and rfloat.copysign(1., val) < 0: + if val == 0.0 and math.copysign(1., val) < 0: w_key = space.newtuple([obj, space.w_float, space.w_None]) else: w_key = space.newtuple([obj, space.w_float]) @@ -279,9 +279,9 @@ real = space.float_w(w_real) imag = space.float_w(w_imag) real_negzero = (real == 0.0 and - rfloat.copysign(1., real) < 0) + math.copysign(1., real) < 0) imag_negzero = (imag == 0.0 and - rfloat.copysign(1., imag) < 0) + math.copysign(1., imag) < 0) if real_negzero and imag_negzero: tup = [obj, space.w_complex, space.w_None, space.w_None, space.w_None] diff --git a/pypy/module/__builtin__/operation.py b/pypy/module/__builtin__/operation.py --- a/pypy/module/__builtin__/operation.py +++ b/pypy/module/__builtin__/operation.py @@ -2,6 +2,8 @@ Interp-level implementation of the basic space operations. """ +import math + from pypy.interpreter import gateway from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.gateway import unwrap_spec, WrappedDefault diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -58,6 +58,14 @@ } +class PyPyDateTime(MixedModule): + appleveldefs = {} + interpleveldefs = { + 'dateinterop': 'interp_pypydatetime.W_DateTime_Date', + 'timeinterop' : 'interp_pypydatetime.W_DateTime_Time', + 'deltainterop' : 'interp_pypydatetime.W_DateTime_Delta', + } + class Module(MixedModule): """ PyPy specific "magic" functions. A lot of them are experimental and subject to change, many are internal. """ @@ -107,6 +115,7 @@ "thread": ThreadModule, "intop": IntOpModule, "os": OsModule, + '_pypydatetime': PyPyDateTime, } def setup_after_space_initialization(self): diff --git a/pypy/module/__pypy__/interp_pypydatetime.py b/pypy/module/__pypy__/interp_pypydatetime.py new file mode 100644 --- /dev/null +++ b/pypy/module/__pypy__/interp_pypydatetime.py @@ -0,0 +1,24 @@ +from pypy.interpreter.baseobjspace import W_Root +from pypy.interpreter.typedef import TypeDef +from pypy.interpreter.gateway import interp2app +from rpython.tool.sourcetools import func_with_new_name + +def create_class(name): + class W_Class(W_Root): + 'builtin base clasee for datetime.%s to allow interop with cpyext' % name + def descr_new__(space, w_type): + return space.allocate_instance(W_Class, w_type) + + W_Class.typedef = TypeDef(name, + __new__ = interp2app(func_with_new_name( + W_Class.descr_new__.im_func, + '%s_new' % (name,))), + ) + W_Class.typedef.acceptable_as_base_class = True + return W_Class + +W_DateTime_Time = create_class('pypydatetime_time') +W_DateTime_Date = create_class('pypydatetime_date') +W_DateTime_Delta = create_class('pypydatetime_delta') + + diff --git a/pypy/module/cmath/test/test_cmath.py b/pypy/module/cmath/test/test_cmath.py --- a/pypy/module/cmath/test/test_cmath.py +++ b/pypy/module/cmath/test/test_cmath.py @@ -1,5 +1,4 @@ from __future__ import with_statement -from rpython.rlib.rfloat import copysign, isnan, isinf from pypy.module.cmath import interp_cmath import os, sys, math @@ -11,7 +10,7 @@ assert isinstance(sqrt_special_values[5][1], tuple) assert sqrt_special_values[5][1][0] == 1e200 * 1e200 assert sqrt_special_values[5][1][1] == -0. - assert copysign(1., sqrt_special_values[5][1][1]) == -1. + assert math.copysign(1., sqrt_special_values[5][1][1]) == -1. class AppTestCMath: @@ -170,12 +169,12 @@ """ # special values testing - if isnan(a): - if isnan(b): + if math.isnan(a): + if math.isnan(b): return raise AssertionError(msg + '%r should be nan' % (b,)) - if isinf(a): + if math.isinf(a): if a == b: return raise AssertionError(msg + 'finite result where infinity expected: ' @@ -186,8 +185,7 @@ # and b to have opposite signs; in practice these hardly ever # occur). if not a and not b: - # only check it if we are running on top of CPython >= 2.6 - if sys.version_info >= (2, 6) and copysign(1., a) != copysign(1., b): + if math.copysign(1., a) != math.copysign(1., b): raise AssertionError(msg + 'zero has wrong sign: expected %r, ' 'got %r' % (a, b)) diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py --- a/pypy/module/cpyext/cdatetime.py +++ b/pypy/module/cpyext/cdatetime.py @@ -1,43 +1,28 @@ from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rtyper.annlowlevel import llhelper -from pypy.module.cpyext.pyobject import PyObject, make_ref +from rpython.rlib.rarithmetic import widen +from pypy.module.cpyext.pyobject import (PyObject, make_ref, make_typedescr, + decref) from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct, - PyObjectFields) + PyObjectFields, cts, parse_dir, bootstrap_function, slot_function) from pypy.module.cpyext.import_ import PyImport_Import from pypy.module.cpyext.typeobject import PyTypeObjectPtr from pypy.interpreter.error import OperationError +from pypy.module.__pypy__.interp_pypydatetime import (W_DateTime_Date, + W_DateTime_Time, W_DateTime_Delta) from rpython.tool.sourcetools import func_renamer -# API import function +cts.parse_header(parse_dir / 'cpyext_datetime.h') -PyDateTime_CAPI = cpython_struct( - 'PyDateTime_CAPI', - (('DateType', PyTypeObjectPtr), - ('DateTimeType', PyTypeObjectPtr), - ('TimeType', PyTypeObjectPtr), - ('DeltaType', PyTypeObjectPtr), - ('TZInfoType', PyTypeObjectPtr), - ('Date_FromDate', lltype.Ptr(lltype.FuncType( - [rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr], - PyObject))), - ('Time_FromTime', lltype.Ptr(lltype.FuncType( - [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, - PyObject, PyTypeObjectPtr], - PyObject))), - ('DateTime_FromDateAndTime', lltype.Ptr(lltype.FuncType( - [rffi.INT_real, rffi.INT_real, rffi.INT_real, - rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, - PyObject, PyTypeObjectPtr], - PyObject))), - ('Delta_FromDelta', lltype.Ptr(lltype.FuncType( - [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, - PyTypeObjectPtr], - PyObject))), - )) +PyDateTime_CAPI = cts.gettype('PyDateTime_CAPI') + +datetimeAPI_global = [] @cpython_api([], lltype.Ptr(PyDateTime_CAPI)) def _PyDateTime_Import(space): + if len(datetimeAPI_global) >0: + return datetimeAPI_global[0] datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw', track_allocation=False) @@ -76,21 +61,13 @@ _PyDelta_FromDelta.api_func.functype, _PyDelta_FromDelta.api_func.get_wrapper(space)) + datetimeAPI_global.append(datetimeAPI) return datetimeAPI -PyDateTime_DateStruct = lltype.ForwardReference() -PyDateTime_TimeStruct = lltype.ForwardReference() -PyDateTime_DateTimeStruct = lltype.ForwardReference() -cpython_struct("PyDateTime_Date", PyObjectFields, PyDateTime_DateStruct) -PyDateTime_Date = lltype.Ptr(PyDateTime_DateStruct) -cpython_struct("PyDateTime_Time", PyObjectFields, PyDateTime_TimeStruct) -PyDateTime_Time = lltype.Ptr(PyDateTime_TimeStruct) -cpython_struct("PyDateTime_DateTime", PyObjectFields, PyDateTime_DateTimeStruct) -PyDateTime_DateTime = lltype.Ptr(PyDateTime_DateTimeStruct) - -PyDeltaObjectStruct = lltype.ForwardReference() -cpython_struct("PyDateTime_Delta", PyObjectFields, PyDeltaObjectStruct) -PyDateTime_Delta = lltype.Ptr(PyDeltaObjectStruct) +PyDateTime_Time = cts.gettype('PyDateTime_Time*') +PyDateTime_DateTime = cts.gettype('PyDateTime_DateTime*') +PyDateTime_Date = cts.gettype('PyDateTime_Date*') +PyDateTime_Delta = cts.gettype('PyDateTime_Delta*') # Check functions @@ -102,6 +79,8 @@ return space.is_true( space.appexec([w_obj], """(obj): from datetime import %s as datatype + if not isinstance(obj, datatype): + print datatype return isinstance(obj, datatype) """ % (type_name,))) except OperationError: @@ -129,6 +108,72 @@ PyTZInfo_Check, PyTZInfo_CheckExact = make_check_function( "PyTZInfo_Check", "tzinfo") +@bootstrap_function +def init_datetime(space): + # no realize functions since there are no getters + make_typedescr(W_DateTime_Time.typedef, + basestruct=PyDateTime_Time.TO, + attach=type_attach, + dealloc=type_dealloc, + ) + + # why do we need date_dealloc? Since W_DateTime_Date is the base class for + # app level datetime.date. If a c-extension class uses datetime.date for its + # base class and defines a tp_dealloc, we will get this: + # c_class->tp_dealloc == tp_dealloc_func + # c_class->tp_base == datetime.date, + # datetime.date->tp_dealloc = _PyPy_subtype_dealloc + # datetime.date->tp_base = W_DateTime_Date + # W_DateTime_Date->tp_dealloc = _PyPy_subtype_dealloc + # but _PyPy_subtype_dealloc will call tp_dealloc_func, which can call its + # base's tp_dealloc and we get recursion. So break the recursion by setting + # W_DateTime_Date->tp_dealloc + make_typedescr(W_DateTime_Date.typedef, + basestruct=PyDateTime_DateTime.TO, + dealloc=date_dealloc, + ) + + make_typedescr(W_DateTime_Delta.typedef, + basestruct=PyDateTime_Delta.TO, + attach=timedeltatype_attach, + ) + +def type_attach(space, py_obj, w_obj, w_userdata=None): + '''Fills a newly allocated py_obj from the w_obj + Can be called with a datetime, or a time + ''' + py_datetime = rffi.cast(PyDateTime_Time, py_obj) + w_tzinfo = space.getattr(w_obj, space.newtext('tzinfo')) + if space.is_none(w_tzinfo): + py_datetime.c_hastzinfo = cts.cast('unsigned char', 0) + py_datetime.c_tzinfo = lltype.nullptr(PyObject.TO) + else: + py_datetime.c_hastzinfo = cts.cast('unsigned char', 1) + py_datetime.c_tzinfo = make_ref(space, w_tzinfo) + +@slot_function([PyObject], lltype.Void) +def type_dealloc(space, py_obj): + py_datetime = rffi.cast(PyDateTime_Time, py_obj) + if (widen(py_datetime.c_hastzinfo) != 0): + decref(space, py_datetime.c_tzinfo) + from pypy.module.cpyext.object import _dealloc + _dealloc(space, py_obj) + +@slot_function([PyObject], lltype.Void) +def date_dealloc(space, py_obj): + from pypy.module.cpyext.object import _dealloc + _dealloc(space, py_obj) + +def timedeltatype_attach(space, py_obj, w_obj, w_userdata=None): + "Fills a newly allocated py_obj from the w_obj" + py_delta = rffi.cast(PyDateTime_Delta, py_obj) + days = space.int_w(space.getattr(w_obj, space.newtext('days'))) + py_delta.c_days = cts.cast('int', days) + seconds = space.int_w(space.getattr(w_obj, space.newtext('seconds'))) + py_delta.c_seconds = cts.cast('int', seconds) + microseconds = space.int_w(space.getattr(w_obj, space.newtext('microseconds'))) + py_delta.c_microseconds = cts.cast('int', microseconds) + # Constructors. They are better used as macros. @cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr], diff --git a/pypy/module/cpyext/include/datetime.h b/pypy/module/cpyext/include/datetime.h --- a/pypy/module/cpyext/include/datetime.h +++ b/pypy/module/cpyext/include/datetime.h @@ -4,49 +4,11 @@ extern "C" { #endif -/* Define structure for C API. */ -typedef struct { - /* type objects */ - PyTypeObject *DateType; - PyTypeObject *DateTimeType; - PyTypeObject *TimeType; - PyTypeObject *DeltaType; - PyTypeObject *TZInfoType; - - /* constructors */ - PyObject *(*Date_FromDate)(int, int, int, PyTypeObject*); - PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, - PyObject*, PyTypeObject*); - PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*); - PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*); -} PyDateTime_CAPI; +#include "cpyext_datetime.h" PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI; -#define PyDateTime_IMPORT \ - do { \ - if(PyDateTimeAPI==NULL) \ - PyDateTimeAPI = _PyDateTime_Import(); \ - } while (0) -typedef struct { - PyObject_HEAD -} PyDateTime_Delta; - -typedef struct { - PyObject_HEAD -} PyDateTime_Date; - -typedef struct { - PyObject_HEAD -} PyDateTime_Time; - -typedef struct { - PyObject_HEAD -} PyDateTime_DateTime; - -typedef struct { - PyObject_HEAD -} PyDateTime_TZInfo; +#define PyDateTime_IMPORT (PyDateTimeAPI = _PyDateTime_Import()) /* Macros for accessing constructors in a simplified fashion. */ #define PyDate_FromDate(year, month, day) \ diff --git a/pypy/module/cpyext/parse/cpyext_datetime.h b/pypy/module/cpyext/parse/cpyext_datetime.h new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/parse/cpyext_datetime.h @@ -0,0 +1,52 @@ +/* Define structure for C API. */ +typedef struct { + /* type objects */ + PyTypeObject *DateType; + PyTypeObject *DateTimeType; + PyTypeObject *TimeType; + PyTypeObject *DeltaType; + PyTypeObject *TZInfoType; + + /* constructors */ + PyObject *(*Date_FromDate)(int, int, int, PyTypeObject*); + PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, + PyObject*, PyTypeObject*); + PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*); + PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*); +} PyDateTime_CAPI; + +typedef struct +{ + PyObject_HEAD + int days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */ + int seconds; /* 0 <= seconds < 24*3600 is invariant */ + int microseconds; /* 0 <= microseconds < 1000000 is invariant */ +} PyDateTime_Delta; + +/* The datetime and time types have an optional tzinfo member, + * PyNone if hastzinfo is false. + */ +typedef struct +{ + PyObject_HEAD + unsigned char hastzinfo; + PyObject *tzinfo; +} PyDateTime_Time; + +typedef struct +{ + PyObject_HEAD + unsigned char hastzinfo; + PyObject *tzinfo; +} PyDateTime_DateTime; + + +typedef struct { + PyObject_HEAD +} PyDateTime_Date; + + +typedef struct { + PyObject_HEAD +} PyDateTime_TZInfo; + diff --git a/pypy/module/math/interp_math.py b/pypy/module/math/interp_math.py --- a/pypy/module/math/interp_math.py +++ b/pypy/module/math/interp_math.py @@ -67,15 +67,15 @@ # No exceptions possible. x = _get_double(space, w_x) y = _get_double(space, w_y) - return space.newfloat(rfloat.copysign(x, y)) + return space.newfloat(math.copysign(x, y)) def isinf(space, w_x): """Return True if x is infinity.""" - return space.newbool(rfloat.isinf(_get_double(space, w_x))) + return space.newbool(math.isinf(_get_double(space, w_x))) def isnan(space, w_x): """Return True if x is not a number.""" - return space.newbool(rfloat.isnan(_get_double(space, w_x))) + return space.newbool(math.isnan(_get_double(space, w_x))) def isfinite(space, w_x): """isfinite(x) -> bool @@ -358,14 +358,14 @@ if not rfloat.isfinite(v): if rfloat.isfinite(original): raise oefmt(space.w_OverflowError, "intermediate overflow") - if rfloat.isinf(original): + if math.isinf(original): inf_sum += original special_sum += original del partials[:] else: partials.append(v) if special_sum != 0.0: - if rfloat.isnan(inf_sum): + if math.isnan(inf_sum): raise oefmt(space.w_ValueError, "-inf + inf") return space.newfloat(special_sum) hi = 0.0 diff --git a/pypy/module/micronumpy/test/test_complex.py b/pypy/module/micronumpy/test/test_complex.py --- a/pypy/module/micronumpy/test/test_complex.py +++ b/pypy/module/micronumpy/test/test_complex.py @@ -1,12 +1,12 @@ from __future__ import with_statement +import math import sys from pypy.conftest import option from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import interp2app from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest -from rpython.rlib.rfloat import isnan, isinf, copysign from rpython.rlib.rcomplex import c_pow @@ -21,12 +21,12 @@ """ # special values testing - if isnan(a): - if isnan(b): + if math.isnan(a): + if math.isnan(b): return True,'' raise AssertionError(msg + '%r should be nan' % (b,)) - if isinf(a): + if math.isinf(a): if a == b: return True,'' raise AssertionError(msg + 'finite result where infinity expected: '+ \ @@ -37,8 +37,7 @@ # and b to have opposite signs; in practice these hardly ever # occur). if not a and not b: - # only check it if we are running on top of CPython >= 2.6 - if sys.version_info >= (2, 6) and copysign(1., a) != copysign(1., b): + if math.copysign(1., a) != math.copysign(1., b): raise AssertionError( msg + \ 'zero has wrong sign: expected %r, got %r' % (a, b)) diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py --- a/pypy/module/micronumpy/types.py +++ b/pypy/module/micronumpy/types.py @@ -767,7 +767,7 @@ except ZeroDivisionError: if v1 == v2 == 0.0: return rfloat.NAN - return rfloat.copysign(rfloat.INFINITY, v1 * v2) + return math.copysign(rfloat.INFINITY, v1 * v2) @simple_binary_op def floordiv(self, v1, v2): @@ -776,7 +776,7 @@ except ZeroDivisionError: if v1 == v2 == 0.0: return rfloat.NAN - return rfloat.copysign(rfloat.INFINITY, v1 * v2) + return math.copysign(rfloat.INFINITY, v1 * v2) @simple_binary_op def mod(self, v1, v2): @@ -793,7 +793,7 @@ # fmod returns different results across platforms; ensure # it has the same sign as the denominator; we'd like to do # "mod = v2 * 0.0", but that may get optimized away - mod = rfloat.copysign(0.0, v2) + mod = math.copysign(0.0, v2) return mod @simple_binary_op @@ -805,7 +805,7 @@ except OverflowError: if math.modf(v2)[0] == 0 and math.modf(v2 / 2)[0] != 0: # Odd integer powers result in the same sign as the base - return rfloat.copysign(rfloat.INFINITY, v1) + return math.copysign(rfloat.INFINITY, v1) return rfloat.INFINITY @simple_binary_op @@ -816,13 +816,13 @@ def sign(self, v): if v == 0.0: return 0.0 - if rfloat.isnan(v): + if math.isnan(v): return rfloat.NAN - return rfloat.copysign(1.0, v) + return math.copysign(1.0, v) @raw_unary_op def signbit(self, v): - return rfloat.copysign(1.0, v) < 0.0 + return math.copysign(1.0, v) < 0.0 @simple_unary_op def fabs(self, v): @@ -830,27 +830,27 @@ @simple_binary_op def max(self, v1, v2): - return v1 if v1 >= v2 or rfloat.isnan(v1) else v2 + return v1 if v1 >= v2 or math.isnan(v1) else v2 @simple_binary_op def min(self, v1, v2): - return v1 if v1 <= v2 or rfloat.isnan(v1) else v2 + return v1 if v1 <= v2 or math.isnan(v1) else v2 @raw_binary_op def argmax(self, v1, v2): - return v1 >= v2 or rfloat.isnan(v1) + return v1 >= v2 or math.isnan(v1) @raw_binary_op def argmin(self, v1, v2): - return v1 <= v2 or rfloat.isnan(v1) + return v1 <= v2 or math.isnan(v1) @simple_binary_op def fmax(self, v1, v2): - return v1 if v1 >= v2 or rfloat.isnan(v2) else v2 + return v1 if v1 >= v2 or math.isnan(v2) else v2 @simple_binary_op def fmin(self, v1, v2): - return v1 if v1 <= v2 or rfloat.isnan(v2) else v2 + return v1 if v1 <= v2 or math.isnan(v2) else v2 @simple_binary_op def fmod(self, v1, v2): @@ -862,7 +862,7 @@ @simple_unary_op def reciprocal(self, v): if v == 0.0: - return rfloat.copysign(rfloat.INFINITY, v) + return math.copysign(rfloat.INFINITY, v) return 1.0 / v @simple_unary_op @@ -876,9 +876,9 @@ @specialize.argtype(1) def round(self, v, decimals=0): raw = self.for_computation(self.unbox(v)) - if rfloat.isinf(raw): + if math.isinf(raw): return v - elif rfloat.isnan(raw): + elif math.isnan(raw): return v ans = rfloat.round_double(raw, decimals, half_even=True) return self.box(ans) @@ -986,11 +986,11 @@ @raw_unary_op def isnan(self, v): - return rfloat.isnan(v) + return math.isnan(v) @raw_unary_op def isinf(self, v): - return rfloat.isinf(v) + return math.isinf(v) @raw_unary_op def isfinite(self, v): @@ -1189,7 +1189,7 @@ return imag_str real_str = str_format(real) - op = '+' if imag >= 0 or rfloat.isnan(imag) else '' + op = '+' if imag >= 0 or math.isnan(imag) else '' return ''.join(['(', real_str, op, imag_str, ')']) def runpack_str(self, space, s, native): @@ -1318,7 +1318,7 @@ return rcomplex.c_div(v1, v2) except ZeroDivisionError: if rcomplex.c_abs(*v1) == 0 or \ - (rfloat.isnan(v1[0]) and rfloat.isnan(v1[1])): + (math.isnan(v1[0]) and math.isnan(v1[1])): return rfloat.NAN, rfloat.NAN return rfloat.INFINITY, rfloat.INFINITY @@ -1353,12 +1353,12 @@ @raw_unary_op def isnan(self, v): '''a complex number is nan if one of the parts is nan''' - return rfloat.isnan(v[0]) or rfloat.isnan(v[1]) + return math.isnan(v[0]) or math.isnan(v[1]) @raw_unary_op def isinf(self, v): '''a complex number is inf if one of the parts is inf''' - return rfloat.isinf(v[0]) or rfloat.isinf(v[1]) + return math.isinf(v[0]) or math.isinf(v[1]) def _eq(self, v1, v2): return v1[0] == v2[0] and v1[1] == v2[1] @@ -1374,7 +1374,7 @@ def _lt(self, v1, v2): (r1, i1), (r2, i2) = v1, v2 - if r1 < r2 and not rfloat.isnan(i1) and not rfloat.isnan(i2): + if r1 < r2 and not math.isnan(i1) and not math.isnan(i2): return True if r1 == r2 and i1 < i2: return True @@ -1459,7 +1459,7 @@ ratio = i2 / r2 denom = r2 + i2 * ratio rr = (r1 + i1 * ratio) / denom - elif rfloat.isnan(r2): + elif math.isnan(r2): rr = rfloat.NAN else: ratio = r2 / i2 @@ -1503,7 +1503,7 @@ sign of complex number could be either the point closest to the unit circle or {-1,0,1}, for compatability with numpy we choose the latter ''' - if rfloat.isnan(v[0]) or rfloat.isnan(v[1]): + if math.isnan(v[0]) or math.isnan(v[1]): return rfloat.NAN, 0 if v[0] == 0.0: if v[1] == 0: @@ -1534,11 +1534,11 @@ @complex_unary_op def reciprocal(self, v): - if rfloat.isinf(v[1]) and rfloat.isinf(v[0]): + if math.isinf(v[1]) and math.isinf(v[0]): return rfloat.NAN, rfloat.NAN - if rfloat.isinf(v[0]): - return (rfloat.copysign(0., v[0]), - rfloat.copysign(0., -v[1])) + if math.isinf(v[0]): + return (math.copysign(0., v[0]), + math.copysign(0., -v[1])) a2 = v[0]*v[0] + v[1]*v[1] try: return rcomplex.c_div((v[0], -v[1]), (a2, 0.)) @@ -1575,13 +1575,13 @@ @complex_unary_op def exp(self, v): - if rfloat.isinf(v[1]): - if rfloat.isinf(v[0]): + if math.isinf(v[1]): + if math.isinf(v[0]): if v[0] < 0: return 0., 0. return rfloat.INFINITY, rfloat.NAN elif (rfloat.isfinite(v[0]) or \ - (rfloat.isinf(v[0]) and v[0] > 0)): + (math.isinf(v[0]) and v[0] > 0)): return rfloat.NAN, rfloat.NAN try: return rcomplex.c_exp(*v) @@ -1603,13 +1603,13 @@ def expm1(self, v): # duplicate exp() so in the future it will be easier # to implement seterr - if rfloat.isinf(v[1]): - if rfloat.isinf(v[0]): + if math.isinf(v[1]): + if math.isinf(v[0]): if v[0] < 0: return -1., 0. return rfloat.NAN, rfloat.NAN elif (rfloat.isfinite(v[0]) or \ - (rfloat.isinf(v[0]) and v[0] > 0)): + (math.isinf(v[0]) and v[0] > 0)): return rfloat.NAN, rfloat.NAN try: res = rcomplex.c_exp(*v) @@ -1622,29 +1622,29 @@ @complex_unary_op def sin(self, v): - if rfloat.isinf(v[0]): + if math.isinf(v[0]): if v[1] == 0.: return rfloat.NAN, 0. if rfloat.isfinite(v[1]): return rfloat.NAN, rfloat.NAN - elif not rfloat.isnan(v[1]): + elif not math.isnan(v[1]): return rfloat.NAN, rfloat.INFINITY return rcomplex.c_sin(*v) @complex_unary_op def cos(self, v): - if rfloat.isinf(v[0]): + if math.isinf(v[0]): if v[1] == 0.: return rfloat.NAN, 0.0 if rfloat.isfinite(v[1]): return rfloat.NAN, rfloat.NAN - elif not rfloat.isnan(v[1]): + elif not math.isnan(v[1]): return rfloat.INFINITY, rfloat.NAN return rcomplex.c_cos(*v) @complex_unary_op def tan(self, v): - if rfloat.isinf(v[0]) and rfloat.isfinite(v[1]): + if math.isinf(v[0]) and rfloat.isfinite(v[1]): return rfloat.NAN, rfloat.NAN return rcomplex.c_tan(*v) @@ -1669,29 +1669,29 @@ @complex_unary_op def sinh(self, v): - if rfloat.isinf(v[1]): + if math.isinf(v[1]): if rfloat.isfinite(v[0]): if v[0] == 0.0: return 0.0, rfloat.NAN return rfloat.NAN, rfloat.NAN - elif not rfloat.isnan(v[0]): + elif not math.isnan(v[0]): return rfloat.INFINITY, rfloat.NAN return rcomplex.c_sinh(*v) @complex_unary_op def cosh(self, v): - if rfloat.isinf(v[1]): + if math.isinf(v[1]): if rfloat.isfinite(v[0]): if v[0] == 0.0: return rfloat.NAN, 0.0 return rfloat.NAN, rfloat.NAN - elif not rfloat.isnan(v[0]): + elif not math.isnan(v[0]): return rfloat.INFINITY, rfloat.NAN return rcomplex.c_cosh(*v) @complex_unary_op def tanh(self, v): - if rfloat.isinf(v[1]) and rfloat.isfinite(v[0]): + if math.isinf(v[1]) and rfloat.isfinite(v[0]): return rfloat.NAN, rfloat.NAN return rcomplex.c_tanh(*v) diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py --- a/pypy/objspace/std/complexobject.py +++ b/pypy/objspace/std/complexobject.py @@ -4,7 +4,7 @@ from rpython.rlib.rarithmetic import intmask, r_ulonglong from rpython.rlib.rbigint import rbigint from rpython.rlib.rfloat import ( - DTSF_STR_PRECISION, copysign, formatd, isinf, isnan, string_to_float) + DTSF_STR_PRECISION, formatd, string_to_float) from rpython.rlib.rstring import ParseStringError from rpython.tool.sourcetools import func_with_new_name @@ -115,12 +115,12 @@ def format_float(x, code, precision): # like float2string, except that the ".0" is not necessary - if isinf(x): + if math.isinf(x): if x > 0.0: return "inf" else: return "-inf" - elif isnan(x): + elif math.isnan(x): return "nan" else: return formatd(x, code, precision) @@ -323,18 +323,18 @@ space.newfloat(self.imagval)]) def descr_repr(self, space): - if self.realval == 0 and copysign(1., self.realval) == 1.: + if self.realval == 0 and math.copysign(1., self.realval) == 1.: return space.newtext(repr_format(self.imagval) + 'j') - sign = (copysign(1., self.imagval) == 1. or - isnan(self.imagval)) and '+' or '' + sign = (math.copysign(1., self.imagval) == 1. or + math.isnan(self.imagval)) and '+' or '' return space.newtext('(' + repr_format(self.realval) + sign + repr_format(self.imagval) + 'j)') def descr_str(self, space): - if self.realval == 0 and copysign(1., self.realval) == 1.: + if self.realval == 0 and math.copysign(1., self.realval) == 1.: return space.newtext(str_format(self.imagval) + 'j') - sign = (copysign(1., self.imagval) == 1. or - isnan(self.imagval)) and '+' or '' + sign = (math.copysign(1., self.imagval) == 1. or + math.isnan(self.imagval)) and '+' or '' return space.newtext('(' + str_format(self.realval) + sign + str_format(self.imagval) + 'j)') diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -8,7 +8,7 @@ from rpython.rlib.rbigint import rbigint from rpython.rlib.rfloat import ( DTSF_ADD_DOT_0, INFINITY, NAN, copysign, - float_as_rbigint_ratio, formatd, isfinite, isinf, isnan) + float_as_rbigint_ratio, formatd, isfinite) from rpython.rlib.rstring import ParseStringError from rpython.rlib.unroll import unrolling_iterable from rpython.rtyper.lltypesystem.module.ll_math import math_fmod @@ -37,7 +37,7 @@ # we special-case explicitly inf and nan here if isfinite(x): s = formatd(x, code, precision, DTSF_ADD_DOT_0) - elif isinf(x): + elif math.isinf(x): if x > 0.0: s = "inf" else: @@ -536,7 +536,7 @@ # fmod returns different results across platforms; ensure # it has the same sign as the denominator; we'd like to do # "mod = y * 0.0", but that may get optimized away - mod = copysign(0.0, y) + mod = math.copysign(0.0, y) return W_FloatObject(mod) @@ -647,7 +647,7 @@ if not isfinite(value): return self.descr_str(space) if value == 0.0: - if copysign(1., value) == -1.: + if math.copysign(1., value) == -1.: return space.newtext("-0x0.0p+0") else: return space.newtext("0x0.0p+0") @@ -731,10 +731,8 @@ def _hash_float(space, v): - if not isfinite(v): - if isinf(v): - return HASH_INF if v > 0 else -HASH_INF - return HASH_NAN + if math.isnan(v): + return 0 m, e = math.frexp(v) @@ -812,16 +810,16 @@ if y == 0.0: # x**0 is 1, even 0**0 return 1.0 - if isnan(x): + if math.isnan(x): # nan**y = nan, unless y == 0 return x - if isnan(y): + if math.isnan(y): # x**nan = nan, unless x == 1; x**nan = x if x == 1.0: return 1.0 else: return y - if isinf(y): + if math.isinf(y): # x**inf is: 0.0 if abs(x) < 1; 1.0 if abs(x) == 1; inf if # abs(x) > 1 (including case where x infinite) # @@ -834,7 +832,7 @@ return INFINITY else: return 0.0 - if isinf(x): + if math.isinf(x): # (+-inf)**w is: inf for w positive, 0 for w negative; in oth # cases, we need to add the appropriate sign if w is an odd # integer. @@ -846,7 +844,7 @@ return abs(x) else: if y_is_odd: - return copysign(0.0, x) + return math.copysign(0.0, x) else: return 0.0 @@ -860,7 +858,7 @@ # unlike "math.pow(-1.0, bignum)". See http://mail.python.org/ # - pipermail/python-bugs-list/2003-March/016795.html if x < 0.0: - if isnan(y): + if math.isnan(y): return NAN if math.floor(y) != y: raise PowDomainError diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py --- a/pypy/objspace/std/formatting.py +++ b/pypy/objspace/std/formatting.py @@ -1,10 +1,11 @@ """String formatting routines""" +import math import sys from rpython.rlib import jit from rpython.rlib.objectmodel import specialize from rpython.rlib.rarithmetic import INT_MAX -from rpython.rlib.rfloat import DTSF_ALT, formatd, isnan, isinf +from rpython.rlib.rfloat import DTSF_ALT, formatd from rpython.rlib.rstring import StringBuilder, UnicodeBuilder from rpython.rlib.unroll import unrolling_iterable from rpython.tool.sourcetools import func_with_new_name @@ -112,12 +113,12 @@ def format_float(self, w_value, char): space = self.space x = space.float_w(maybe_float(space, w_value)) - if isnan(x): + if math.isnan(x): if char in 'EFG': r = 'NAN' else: r = 'nan' - elif isinf(x): + elif math.isinf(x): if x < 0: if char in 'EFG': r = '-INF' diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -7,6 +7,7 @@ """ +import math import operator import sys @@ -1774,11 +1775,9 @@ def _safe_find(self, w_list, obj, start, stop): - from rpython.rlib.rfloat import isnan - # l = self.unerase(w_list.lstorage) stop = min(stop, len(l)) - if not isnan(obj): + if not math.isnan(obj): for i in range(start, stop): val = l[i] if val == obj: diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py --- a/pypy/objspace/std/newformat.py +++ b/pypy/objspace/std/newformat.py @@ -1,12 +1,13 @@ """The unicode/str format() method""" +import math import sys import string from pypy.interpreter.error import OperationError, oefmt from rpython.rlib import rstring, runicode, rlocale, rfloat, jit from rpython.rlib.objectmodel import specialize -from rpython.rlib.rfloat import copysign, formatd +from rpython.rlib.rfloat import formatd from rpython.rlib.rarithmetic import r_uint, intmask from pypy.interpreter.signature import Signature @@ -1047,7 +1048,7 @@ default_precision = 12 #test if real part is non-zero if (w_complex.realval == 0 and - copysign(1., w_complex.realval) == 1.): + math.copysign(1., w_complex.realval) == 1.): skip_re = 1 else: add_parens = 1 diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py --- a/pypy/objspace/std/objspace.py +++ b/pypy/objspace/std/objspace.py @@ -144,7 +144,6 @@ return self.fromcache(TypeCache).getorbuild(typedef) @not_rpython # only for tests - @specialize.argtype(1) def wrap(self, x): """ Wraps the Python value 'x' into one of the wrapper classes. This should only be used for tests, in real code you need to use the diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py --- a/rpython/annotator/model.py +++ b/rpython/annotator/model.py @@ -30,6 +30,7 @@ from __future__ import absolute_import import inspect +import math import weakref from types import BuiltinFunctionType, MethodType from collections import OrderedDict, defaultdict @@ -169,13 +170,12 @@ def __eq__(self, other): if (type(self) is SomeFloat and type(other) is SomeFloat and self.is_constant() and other.is_constant()): - from rpython.rlib.rfloat import isnan, copysign # NaN unpleasantness. - if isnan(self.const) and isnan(other.const): + if math.isnan(self.const) and math.isnan(other.const): return True # 0.0 vs -0.0 unpleasantness. if not self.const and not other.const: - return copysign(1., self.const) == copysign(1., other.const) + return math.copysign(1., self.const) == math.copysign(1., other.const) # return super(SomeFloat, self).__eq__(other) diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -1,4 +1,4 @@ -import py, sys, random, os, struct, operator +import py, sys, random, os, struct, operator, math from rpython.jit.metainterp.history import (AbstractFailDescr, AbstractDescr, BasicFailDescr, @@ -1696,7 +1696,7 @@ if not self.cpu.supports_floats: py.test.skip("requires floats") - from rpython.rlib.rfloat import INFINITY, NAN, isinf, isnan + from rpython.rlib.rfloat import INFINITY, NAN from rpython.jit.metainterp.resoperation import opname fzer = 0.0 @@ -1724,10 +1724,10 @@ expectedtype) if not isinstance(expected, bool): got = longlong.getrealfloat(got) - if isnan(expected): - ok = isnan(got) - elif isinf(expected): - ok = isinf(got) + if math.isnan(expected): + ok = math.isnan(got) + elif math.isinf(expected): + ok = math.isinf(got) else: ok = got == expected if not ok: diff --git a/rpython/jit/metainterp/test/support.py b/rpython/jit/metainterp/test/support.py --- a/rpython/jit/metainterp/test/support.py +++ b/rpython/jit/metainterp/test/support.py @@ -1,5 +1,4 @@ - -import py, sys +import py, sys, math from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.jit.backend.llgraph import runner from rpython.jit.metainterp.warmspot import ll_meta_interp, get_stats @@ -10,7 +9,6 @@ from rpython.jit.codewriter.policy import JitPolicy from rpython.jit.codewriter import codewriter, longlong from rpython.jit.backend.llsupport.vector_ext import VectorExt -from rpython.rlib.rfloat import isnan from rpython.rlib.jit import ENABLE_ALL_OPTS from rpython.translator.backendopt.all import backend_optimizations @@ -274,11 +272,11 @@ result1 = _run_with_blackhole(self, args) # try to run it with pyjitpl.py result2 = _run_with_pyjitpl(self, args, stats) - assert result1 == result2 or isnan(result1) and isnan(result2) + assert result1 == result2 or math.isnan(result1) and math.isnan(result2) # try to run it by running the code compiled just before df, result3 = _run_with_machine_code(self, args) self._lastframe = df - assert result1 == result3 or result3 == NotImplemented or isnan(result1) and isnan(result3) + assert result1 == result3 or result3 == NotImplemented or math.isnan(result1) and math.isnan(result3) # if (longlong.supports_longlong and isinstance(result1, longlong.r_float_storage)): diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -1,3 +1,4 @@ +import math import sys import py @@ -3973,7 +3974,6 @@ assert res == 3 def test_float_bytes(self): - from rpython.rlib.rfloat import isnan def f(n): ll = float2longlong(n) return longlong2float(ll) @@ -3981,7 +3981,7 @@ for x in [2.5, float("nan"), -2.5, float("inf")]: # There are tests elsewhere to verify the correctness of this. res = self.interp_operations(f, [x]) - assert res == x or isnan(x) and isnan(res) + assert res == x or math.isnan(x) and math.isnan(res) class TestLLtype(BaseLLtypeTests, LLJitMixin): diff --git a/rpython/jit/metainterp/test/test_math.py b/rpython/jit/metainterp/test/test_math.py --- a/rpython/jit/metainterp/test/test_math.py +++ b/rpython/jit/metainterp/test/test_math.py @@ -1,6 +1,6 @@ import math from rpython.jit.metainterp.test.support import LLJitMixin -from rpython.rlib.rfloat import isinf, isnan, INFINITY, NAN +from rpython.rlib.rfloat import INFINITY, NAN class MathTests: @@ -32,11 +32,11 @@ self.check_operations_history(call_pure_f=0) # res = self.interp_operations(f, [INFINITY]) - assert isinf(res) and not isnan(res) and res > 0.0 + assert math.isinf(res) and not math.isnan(res) and res > 0.0 self.check_operations_history(call_pure_f=0) # res = self.interp_operations(f, [NAN]) - assert isnan(res) and not isinf(res) + assert math.isnan(res) and not math.isinf(res) self.check_operations_history(call_pure_f=0) diff --git a/rpython/jit/metainterp/test/test_zvector.py b/rpython/jit/metainterp/test/test_zvector.py --- a/rpython/jit/metainterp/test/test_zvector.py +++ b/rpython/jit/metainterp/test/test_zvector.py @@ -11,7 +11,6 @@ from rpython.jit.metainterp import history from rpython.rlib.jit import JitDriver, hint, set_param from rpython.rlib.objectmodel import compute_hash -from rpython.rlib import rfloat from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.rarithmetic import r_uint, intmask, r_int from rpython.rlib.rawstorage import (alloc_raw_storage, raw_storage_setitem, @@ -309,7 +308,7 @@ reds = 'auto', vectorize=True) def fmax(v1, v2): - return v1 if v1 >= v2 or rfloat.isnan(v2) else v2 + return v1 if v1 >= v2 or math.isnan(v2) else v2 T = lltype.Array(rffi.DOUBLE, hints={'nolength': True}) def f(d): i = 0 diff --git a/rpython/rlib/constant.py b/rpython/rlib/constant.py --- a/rpython/rlib/constant.py +++ b/rpython/rlib/constant.py @@ -1,5 +1,4 @@ import math -from rpython.rlib.rfloat import isinf from rpython.rtyper.tool import rffi_platform from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -18,7 +17,7 @@ assert 0.0 < DBL_MAX < (1e200*1e200) -assert isinf(DBL_MAX * 1.0001) +assert math.isinf(DBL_MAX * 1.0001) assert DBL_MIN > 0.0 assert DBL_MIN * (2**-53) == 0.0 diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py --- a/rpython/rlib/objectmodel.py +++ b/rpython/rlib/objectmodel.py @@ -549,9 +549,9 @@ In RPython, floats cannot be used with ints in dicts, anyway. """ from rpython.rlib.rarithmetic import intmask - from rpython.rlib.rfloat import isfinite, isinf + from rpython.rlib.rfloat import isfinite if not isfinite(f): - if isinf(f): + if math.isinf(f): if f < 0.0: return -271828 else: diff --git a/rpython/rlib/rarithmetic.py b/rpython/rlib/rarithmetic.py --- a/rpython/rlib/rarithmetic.py +++ b/rpython/rlib/rarithmetic.py @@ -36,7 +36,7 @@ """ -import sys, struct +import sys, struct, math from rpython.rtyper import extregistry from rpython.rlib import objectmodel from rpython.flowspace.model import Constant, const @@ -191,8 +191,7 @@ # Note the "<= x <" here, as opposed to "< x <" above. # This is justified by test_typed in translator/c/test. def ovfcheck_float_to_longlong(x): - from rpython.rlib.rfloat import isnan - if isnan(x): + if math.isnan(x): raise OverflowError if -9223372036854776832.0 <= x < 9223372036854775296.0: return r_longlong(x) @@ -200,8 +199,7 @@ if sys.maxint == 2147483647: def ovfcheck_float_to_int(x): - from rpython.rlib.rfloat import isnan - if isnan(x): + if math.isnan(x): raise OverflowError if -2147483649.0 < x < 2147483648.0: return int(x) diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py --- a/rpython/rlib/rbigint.py +++ b/rpython/rlib/rbigint.py @@ -1,7 +1,6 @@ from rpython.rlib.rarithmetic import LONG_BIT, intmask, longlongmask, r_uint, r_ulonglong from rpython.rlib.rarithmetic import ovfcheck, r_longlong, widen from rpython.rlib.rarithmetic import most_neg_value_of_same_type -from rpython.rlib.rfloat import isinf, isnan from rpython.rlib.rstring import StringBuilder from rpython.rlib.debug import make_sure_not_resized, check_regular_int from rpython.rlib.objectmodel import we_are_translated, specialize, not_rpython @@ -227,9 +226,9 @@ def fromfloat(dval): """ Create a new bigint object from a float """ # This function is not marked as pure because it can raise - if isinf(dval): + if math.isinf(dval): raise OverflowError("cannot convert float infinity to integer") - if isnan(dval): + if math.isnan(dval): raise ValueError("cannot convert float NaN to integer") return rbigint._fromfloat_finite(dval) diff --git a/rpython/rlib/rcomplex.py b/rpython/rlib/rcomplex.py --- a/rpython/rlib/rcomplex.py +++ b/rpython/rlib/rcomplex.py @@ -1,6 +1,6 @@ import math from math import fabs -from rpython.rlib.rfloat import copysign, asinh, log1p, isfinite, isinf, isnan +from rpython.rlib.rfloat import asinh, log1p, isfinite from rpython.rlib.constant import DBL_MIN, CM_SCALE_UP, CM_SCALE_DOWN from rpython.rlib.constant import CM_LARGE_DOUBLE, DBL_MANT_DIG from rpython.rlib.constant import M_LN2, M_LN10 @@ -57,7 +57,7 @@ denom = r2 + i2 * ratio rr = (r1 + i1 * ratio) / denom ir = (i1 - r1 * ratio) / denom - elif isnan(r2): + elif math.isnan(r2): rr = NAN ir = NAN else: @@ -151,9 +151,9 @@ d = ay/(2.*s) if x >= 0.: - return (s, copysign(d, y)) + return (s, math.copysign(d, y)) else: - return (d, copysign(s, y)) + return (d, math.copysign(s, y)) @@ -167,10 +167,10 @@ # split into cases to make sure that the branch cut has the # correct continuity on systems with unsigned zeros if x < 0.: - imag = -copysign(math.log(math.hypot(x/2., y/2.)) + + imag = -math.copysign(math.log(math.hypot(x/2., y/2.)) + M_LN2*2., y) else: - imag = copysign(math.log(math.hypot(x/2., y/2.)) + + imag = math.copysign(math.log(math.hypot(x/2., y/2.)) + M_LN2*2., -y) else: s1x, s1y = c_sqrt(1.-x, -y) @@ -210,10 +210,10 @@ if fabs(x) > CM_LARGE_DOUBLE or fabs(y) > CM_LARGE_DOUBLE: if y >= 0.: - real = copysign(math.log(math.hypot(x/2., y/2.)) + + real = math.copysign(math.log(math.hypot(x/2., y/2.)) + M_LN2*2., x) else: - real = -copysign(math.log(math.hypot(x/2., y/2.)) + + real = -math.copysign(math.log(math.hypot(x/2., y/2.)) + M_LN2*2., -x) imag = math.atan2(y, fabs(x)) else: @@ -249,7 +249,7 @@ # except when working with unsigned zeros: they're there to # ensure that the branch cut has the correct continuity on # systems that don't support signed zeros - imag = -copysign(math.pi/2., -y) + imag = -math.copysign(math.pi/2., -y) elif x == 1. and ay < CM_SQRT_DBL_MIN: # C99 standard says: atanh(1+/-0.) should be inf +/- 0i if ay == 0.: @@ -258,7 +258,7 @@ #imag = y else: real = -math.log(math.sqrt(ay)/math.sqrt(math.hypot(ay, 2.))) - imag = copysign(math.atan2(2., -ay) / 2, y) + imag = math.copysign(math.atan2(2., -ay) / 2, y) else: real = log1p(4.*x/((1-x)*(1-x) + ay*ay))/4. imag = -math.atan2(-2.*y, (1-x)*(1+x) - ay*ay) / 2. @@ -330,20 +330,20 @@ def c_exp(x, y): if not isfinite(x) or not isfinite(y): - if isinf(x) and isfinite(y) and y != 0.: + if math.isinf(x) and isfinite(y) and y != 0.: if x > 0: - real = copysign(INF, math.cos(y)) - imag = copysign(INF, math.sin(y)) + real = math.copysign(INF, math.cos(y)) + imag = math.copysign(INF, math.sin(y)) else: - real = copysign(0., math.cos(y)) - imag = copysign(0., math.sin(y)) + real = math.copysign(0., math.cos(y)) + imag = math.copysign(0., math.sin(y)) r = (real, imag) else: r = exp_special_values[special_type(x)][special_type(y)] # need to raise ValueError if y is +/- infinity and x is not # a NaN and not -infinity - if isinf(y) and (isfinite(x) or (isinf(x) and x > 0)): + if math.isinf(y) and (isfinite(x) or (math.isinf(x) and x > 0)): raise ValueError("math domain error") return r @@ -355,40 +355,40 @@ l = math.exp(x) real = l * math.cos(y) imag = l * math.sin(y) - if isinf(real) or isinf(imag): + if math.isinf(real) or math.isinf(imag): raise OverflowError("math range error") return real, imag def c_cosh(x, y): if not isfinite(x) or not isfinite(y): - if isinf(x) and isfinite(y) and y != 0.: + if math.isinf(x) and isfinite(y) and y != 0.: if x > 0: - real = copysign(INF, math.cos(y)) - imag = copysign(INF, math.sin(y)) + real = math.copysign(INF, math.cos(y)) + imag = math.copysign(INF, math.sin(y)) else: - real = copysign(INF, math.cos(y)) - imag = -copysign(INF, math.sin(y)) + real = math.copysign(INF, math.cos(y)) + imag = -math.copysign(INF, math.sin(y)) r = (real, imag) else: r = cosh_special_values[special_type(x)][special_type(y)] # need to raise ValueError if y is +/- infinity and x is not # a NaN - if isinf(y) and not isnan(x): + if math.isinf(y) and not math.isnan(x): raise ValueError("math domain error") return r if fabs(x) > CM_LOG_LARGE_DOUBLE: # deal correctly with cases where cosh(x) overflows but # cosh(z) does not. - x_minus_one = x - copysign(1., x) + x_minus_one = x - math.copysign(1., x) real = math.cos(y) * math.cosh(x_minus_one) * math.e imag = math.sin(y) * math.sinh(x_minus_one) * math.e else: real = math.cos(y) * math.cosh(x) imag = math.sin(y) * math.sinh(x) - if isinf(real) or isinf(imag): + if math.isinf(real) or math.isinf(imag): raise OverflowError("math range error") return real, imag @@ -396,31 +396,31 @@ def c_sinh(x, y): # special treatment for sinh(+/-inf + iy) if y is finite and nonzero if not isfinite(x) or not isfinite(y): - if isinf(x) and isfinite(y) and y != 0.: + if math.isinf(x) and isfinite(y) and y != 0.: if x > 0: - real = copysign(INF, math.cos(y)) - imag = copysign(INF, math.sin(y)) + real = math.copysign(INF, math.cos(y)) + imag = math.copysign(INF, math.sin(y)) else: - real = -copysign(INF, math.cos(y)) - imag = copysign(INF, math.sin(y)) + real = -math.copysign(INF, math.cos(y)) + imag = math.copysign(INF, math.sin(y)) r = (real, imag) else: r = sinh_special_values[special_type(x)][special_type(y)] # need to raise ValueError if y is +/- infinity and x is not # a NaN - if isinf(y) and not isnan(x): + if math.isinf(y) and not math.isnan(x): raise ValueError("math domain error") return r if fabs(x) > CM_LOG_LARGE_DOUBLE: - x_minus_one = x - copysign(1., x) + x_minus_one = x - math.copysign(1., x) real = math.cos(y) * math.sinh(x_minus_one) * math.e imag = math.sin(y) * math.cosh(x_minus_one) * math.e else: real = math.cos(y) * math.sinh(x) imag = math.sin(y) * math.cosh(x) - if isinf(real) or isinf(imag): + if math.isinf(real) or math.isinf(imag): raise OverflowError("math range error") return real, imag @@ -437,24 +437,24 @@ # computation of cosh(x). if not isfinite(x) or not isfinite(y): - if isinf(x) and isfinite(y) and y != 0.: + if math.isinf(x) and isfinite(y) and y != 0.: if x > 0: real = 1.0 # vv XXX why is the 2. there? - imag = copysign(0., 2. * math.sin(y) * math.cos(y)) + imag = math.copysign(0., 2. * math.sin(y) * math.cos(y)) else: real = -1.0 - imag = copysign(0., 2. * math.sin(y) * math.cos(y)) + imag = math.copysign(0., 2. * math.sin(y) * math.cos(y)) r = (real, imag) else: r = tanh_special_values[special_type(x)][special_type(y)] # need to raise ValueError if y is +/-infinity and x is finite - if isinf(y) and isfinite(x): + if math.isinf(y) and isfinite(x): raise ValueError("math domain error") return r if fabs(x) > CM_LOG_LARGE_DOUBLE: - real = copysign(1., x) + real = math.copysign(1., x) imag = 4. * math.sin(y) * math.cos(y) * math.exp(-2.*fabs(x)) else: tx = math.tanh(x) @@ -487,20 +487,20 @@ # if r is +/-infinity and phi is finite but nonzero then # result is (+-INF +-INF i), but we need to compute cos(phi) # and sin(phi) to figure out the signs. - if isinf(r) and isfinite(phi) and phi != 0.: + if math.isinf(r) and isfinite(phi) and phi != 0.: if r > 0: - real = copysign(INF, math.cos(phi)) - imag = copysign(INF, math.sin(phi)) + real = math.copysign(INF, math.cos(phi)) + imag = math.copysign(INF, math.sin(phi)) else: - real = -copysign(INF, math.cos(phi)) - imag = -copysign(INF, math.sin(phi)) + real = -math.copysign(INF, math.cos(phi)) + imag = -math.copysign(INF, math.sin(phi)) z = (real, imag) else: z = rect_special_values[special_type(r)][special_type(phi)] # need to raise ValueError if r is a nonzero number and phi # is infinite - if r != 0. and not isnan(r) and isinf(phi): + if r != 0. and not math.isnan(r) and math.isinf(phi): raise ValueError("math domain error") return z @@ -512,25 +512,25 @@ def c_phase(x, y): # Windows screws up atan2 for inf and nan, and alpha Tru64 5.1 doesn't # follow C99 for atan2(0., 0.). - if isnan(x) or isnan(y): + if math.isnan(x) or math.isnan(y): return NAN - if isinf(y): - if isinf(x): - if copysign(1., x) == 1.: + if math.isinf(y): + if math.isinf(x): + if math.copysign(1., x) == 1.: # atan2(+-inf, +inf) == +-pi/4 - return copysign(0.25 * math.pi, y) + return math.copysign(0.25 * math.pi, y) else: # atan2(+-inf, -inf) == +-pi*3/4 - return copysign(0.75 * math.pi, y) + return math.copysign(0.75 * math.pi, y) # atan2(+-inf, x) == +-pi/2 for finite x - return copysign(0.5 * math.pi, y) - if isinf(x) or y == 0.: - if copysign(1., x) == 1.: + return math.copysign(0.5 * math.pi, y) + if math.isinf(x) or y == 0.: + if math.copysign(1., x) == 1.: # atan2(+-y, +inf) = atan2(+-0, +x) = +-0. - return copysign(0., y) + return math.copysign(0., y) else: # atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. - return copysign(math.pi, y) + return math.copysign(math.pi, y) return math.atan2(y, x) @@ -538,9 +538,9 @@ if not isfinite(r) or not isfinite(i): # C99 rules: if either the real or the imaginary part is an # infinity, return infinity, even if the other part is a NaN. - if isinf(r): + if math.isinf(r): return INF - if isinf(i): + if math.isinf(i): return INF # either the real or imaginary part is a NaN, @@ -560,11 +560,11 @@ def c_isinf(r, i): - return isinf(r) or isinf(i) + return math.isinf(r) or math.isinf(i) def c_isnan(r, i): - return isnan(r) or isnan(i) + return math.isnan(r) or math.isnan(i) def c_isfinite(r, i): diff --git a/rpython/rlib/rfloat.py b/rpython/rlib/rfloat.py --- a/rpython/rlib/rfloat.py +++ b/rpython/rlib/rfloat.py @@ -1,7 +1,7 @@ """Float constants""" import math, struct -from math import isinf, isnan, copysign, acosh, asinh, atanh, log1p, expm1 +from math import acosh, asinh, atanh, log1p, expm1 from rpython.annotator.model import SomeString, SomeChar from rpython.rlib import objectmodel, unroll @@ -85,7 +85,7 @@ def double_to_string(value, tp, precision, flags): if isfinite(value): special = DIST_FINITE - elif isinf(value): + elif math.isinf(value): special = DIST_INFINITY else: #isnan(value): special = DIST_NAN @@ -131,7 +131,7 @@ # multiple of 0.5 * 10**n for n >= 23 takes at least 54 bits of # precision to represent exactly. - sign = copysign(1.0, value) + sign = math.copysign(1.0, value) value = abs(value) # find 2-valuation value @@ -204,7 +204,7 @@ # (a) produce exact results for powers of 2, and # (b) be monotonic, assuming that the system log is monotonic. if not isfinite(x): - if isnan(x): + if math.isnan(x): return x # log2(nan) = nan elif x > 0.0: return x # log2(+inf) = +inf @@ -234,7 +234,7 @@ absx = abs(x) r = math.floor(absx + 0.5) if r - absx < 1.0: - return copysign(r, x) + return math.copysign(r, x) else: # 'absx' is just in the wrong range: its exponent is precisely # the one for which all integers are representable but not any @@ -258,18 +258,18 @@ # absx == n + 0.5 for a non-negative integer 'n' # absx * 0.5 == n//2 + 0.25 or 0.75, which we round to nearest r = math.floor(absx * 0.5 + 0.5) * 2.0 - return copysign(r, x) + return math.copysign(r, x) @not_rpython def isfinite(x): - return not isinf(x) and not isnan(x) + return not math.isinf(x) and not math.isnan(x) def float_as_rbigint_ratio(value): from rpython.rlib.rbigint import rbigint - if isinf(value): + if math.isinf(value): raise OverflowError("cannot pass infinity to as_integer_ratio()") - elif isnan(value): + elif math.isnan(value): raise ValueError("cannot pass nan to as_integer_ratio()") float_part, exp_int = math.frexp(value) for i in range(300): @@ -327,7 +327,7 @@ def erf(x): """The error function at x.""" - if isnan(x): + if math.isnan(x): return x absx = abs(x) if absx < ERF_SERIES_CUTOFF: @@ -338,7 +338,7 @@ def erfc(x): """The complementary error function at x.""" - if isnan(x): + if math.isnan(x): return x absx = abs(x) if absx < ERF_SERIES_CUTOFF: @@ -362,7 +362,7 @@ r = math.sin(math.pi * (y - 2.)) else: raise AssertionError("should not reach") - return copysign(1., x) * r + return math.copysign(1., x) * r _lanczos_g = 6.024680040776729583740234375 _lanczos_g_minus_half = 5.524680040776729583740234375 @@ -410,9 +410,9 @@ def gamma(x): """Compute the gamma function for x.""" - if isnan(x) or (isinf(x) and x > 0.): + if math.isnan(x) or (math.isinf(x) and x > 0.): return x - if isinf(x): + if math.isinf(x): raise ValueError("math domain error") if x == 0.: raise ValueError("math domain error") @@ -424,7 +424,7 @@ absx = abs(x) if absx < 1e-20: r = 1. / x - if isinf(r): + if math.isinf(r): raise OverflowError("math range error") return r if absx > 200.: @@ -458,15 +458,15 @@ sqrtpow = math.pow(y, absx / 2. - .25) r *= sqrtpow r *= sqrtpow - if isinf(r): + if math.isinf(r): raise OverflowError("math range error") return r def lgamma(x): """Compute the natural logarithm of the gamma function for x.""" - if isnan(x): + if math.isnan(x): return x - if isinf(x): + if math.isinf(x): return INFINITY if x == math.floor(x) and x <= 2.: if x <= 0.: @@ -482,7 +482,7 @@ r = (math.log(math.pi) - math.log(abs(_sinpi(absx))) - math.log(absx) - (math.log(_lanczos_sum(absx)) - _lanczos_g + (absx - .5) * (math.log(absx + _lanczos_g - .5) - 1))) - if isinf(r): + if math.isinf(r): raise OverflowError("math domain error") return r diff --git a/rpython/rlib/rstruct/ieee.py b/rpython/rlib/rstruct/ieee.py --- a/rpython/rlib/rstruct/ieee.py +++ b/rpython/rlib/rstruct/ieee.py @@ -151,11 +151,11 @@ else: raise ValueError("invalid size value") - sign = rfloat.copysign(1.0, x) < 0.0 - if rfloat.isinf(x): + sign = math.copysign(1.0, x) < 0.0 + if math.isinf(x): mant = r_ulonglong(0) exp = MAX_EXP - MIN_EXP + 2 - elif rfloat.isnan(x): + elif math.isnan(x): asint = cast(ULONGLONG, float2longlong(x)) sign = asint >> 63 # shift off lower bits, perhaps losing data @@ -216,11 +216,11 @@ else: raise ValueError("invalid size value") - sign = rfloat.copysign(1.0, x) < 0.0 - if rfloat.isinf(x): + sign = math.copysign(1.0, x) < 0.0 + if math.isinf(x): mant = r_ulonglong(0) exp = MAX_EXP - MIN_EXP + 2 - elif rfloat.isnan(x): # rfloat.isnan(x): + elif math.isnan(x): asint = cast(ULONGLONG, float2longlong(x)) mant = asint & ((r_ulonglong(1) << 51) - 1) if mant == 0: diff --git a/rpython/rlib/rstruct/test/test_ieee.py b/rpython/rlib/rstruct/test/test_ieee.py --- a/rpython/rlib/rstruct/test/test_ieee.py +++ b/rpython/rlib/rstruct/test/test_ieee.py @@ -1,3 +1,4 @@ +import math import py import sys import random @@ -5,7 +6,7 @@ from rpython.rlib.mutbuffer import MutableStringBuffer from rpython.rlib.rstruct import ieee -from rpython.rlib.rfloat import isnan, NAN, INFINITY +from rpython.rlib.rfloat import NAN, INFINITY from rpython.translator.c.test.test_genc import compile @@ -30,7 +31,6 @@ assert f == ieee.float_unpack(h, 2) def test_halffloat_overunderflow(self): - import math cases = [[670000, float('inf')], [-67000, -float('inf')], [1e-08, 0], [-1e-8, -0.]] for f1, f2 in cases: @@ -59,9 +59,6 @@ class TestFloatPacking: - def setup_class(cls): - if sys.version_info < (2, 6): - py.test.skip("the 'struct' module of this old CPython is broken") def check_float(self, x): # check roundtrip @@ -176,7 +173,7 @@ # nans are tricky: we can't hope to reproduce the bit # pattern exactly, so check_float will fail for a nan # whose mantissa does not fit into float16's mantissa. - if isnan(x) and (Q & mantissa_mask) >= 1 << 11: + if math.isnan(x) and (Q & mantissa_mask) >= 1 << 11: continue self.check_float(x) @@ -189,7 +186,7 @@ for i in range(20): val_to_preserve = exp | ((maxmant16 - i) << 42) a = ieee.float_unpack(val_to_preserve, 8) - assert isnan(a), 'i %d, maxmant %s' % (i, hex(val_to_preserve)) + assert math.isnan(a), 'i %d, maxmant %s' % (i, hex(val_to_preserve)) b = ieee.float_pack(a, 8) assert b == val_to_preserve, 'i %d, val %s b %s' % (i, hex(val_to_preserve), hex(b)) b = ieee.float_pack(a, 2) @@ -214,14 +211,14 @@ def check_roundtrip(x, size): s = c_pack(x, size) - if not isnan(x): + if not math.isnan(x): # pack uses copysign which is ambiguous for NAN assert s == pack(x, size) assert unpack(s) == x assert c_unpack(s) == x else: - assert isnan(unpack(s)) - assert isnan(c_unpack(s)) + assert math.isnan(unpack(s)) + assert math.isnan(c_unpack(s)) for size in [2, 4, 8]: check_roundtrip(123.4375, size) diff --git a/rpython/rlib/special_value.py b/rpython/rlib/special_value.py --- a/rpython/rlib/special_value.py +++ b/rpython/rlib/special_value.py @@ -1,5 +1,4 @@ import math -from rpython.rlib.rfloat import isnan, isinf, copysign # code to deal with special values (infinities, NaNs, ...) # @@ -13,9 +12,9 @@ ST_NAN = 6 # Not a Number def special_type(d): - if isnan(d): + if math.isnan(d): return ST_NAN - elif isinf(d): + elif math.isinf(d): if d > 0.0: return ST_PINF else: @@ -27,7 +26,7 @@ else: return ST_NEG else: - if copysign(1., d) == 1.: + if math.copysign(1., d) == 1.: return ST_PZERO else: return ST_NZERO @@ -166,4 +165,4 @@ (N,N), (N,N), (N,Z), (N,Z), (N,N), (N,N), (N,N), ]) -assert copysign(1., acosh_special_values[5][2][1]) == -1. +assert math.copysign(1., acosh_special_values[5][2][1]) == -1. diff --git a/rpython/rlib/test/test_longlong2float.py b/rpython/rlib/test/test_longlong2float.py --- a/rpython/rlib/test/test_longlong2float.py +++ b/rpython/rlib/test/test_longlong2float.py @@ -1,3 +1,4 @@ +import math from rpython.translator.c.test.test_genc import compile from rpython.rlib.longlong2float import longlong2float, float2longlong from rpython.rlib.longlong2float import uint2singlefloat, singlefloat2uint @@ -74,7 +75,6 @@ from rpython.rlib.longlong2float import encode_int32_into_longlong_nan from rpython.rlib.longlong2float import decode_int32_from_longlong_nan from rpython.rlib.longlong2float import is_int32_from_longlong_nan - from rpython.rlib.rfloat import isnan assert can_encode_float(f1) assert can_encode_int32(i2) l1 = float2longlong(f1) @@ -82,7 +82,7 @@ assert not is_int32_from_longlong_nan(l1) assert is_int32_from_longlong_nan(l2) f1b = longlong2float(l1) - assert f1b == f1 or (isnan(f1b) and isnan(f1)) + assert f1b == f1 or (math.isnan(f1b) and math.isnan(f1)) assert decode_int32_from_longlong_nan(l2) == i2 return 42 diff --git a/rpython/rlib/test/test_rcomplex.py b/rpython/rlib/test/test_rcomplex.py --- a/rpython/rlib/test/test_rcomplex.py +++ b/rpython/rlib/test/test_rcomplex.py @@ -1,7 +1,6 @@ from __future__ import with_statement import rpython.rlib.rcomplex as c -from rpython.rlib.rfloat import copysign, isnan, isinf import os, sys, math, struct @@ -120,12 +119,12 @@ """ # special values testing - if isnan(a): - if isnan(b): + if math.isnan(a): + if math.isnan(b): return raise AssertionError(msg + '%r should be nan' % (b,)) - if isinf(a): + if math.isinf(a): if a == b: return raise AssertionError(msg + 'finite result where infinity expected: ' @@ -136,8 +135,7 @@ # and b to have opposite signs; in practice these hardly ever # occur). if not a and not b: - # only check it if we are running on top of CPython >= 2.6 - if sys.version_info >= (2, 6) and copysign(1., a) != copysign(1., b): + if math.copysign(1., a) != math.copysign(1., b): raise AssertionError(msg + 'zero has wrong sign: expected %r, ' 'got %r' % (a, b)) diff --git a/rpython/rlib/test/test_rfloat.py b/rpython/rlib/test/test_rfloat.py --- a/rpython/rlib/test/test_rfloat.py +++ b/rpython/rlib/test/test_rfloat.py @@ -1,21 +1,13 @@ -import sys, py +import sys, py, math from rpython.rlib.rfloat import float_as_rbigint_ratio -from rpython.rlib.rfloat import copysign from rpython.rlib.rfloat import round_away from rpython.rlib.rfloat import round_double -from rpython.rlib.rfloat import erf, erfc, gamma, lgamma, isnan +from rpython.rlib.rfloat import erf, erfc, gamma, lgamma from rpython.rlib.rfloat import ulps_check, acc_check from rpython.rlib.rfloat import string_to_float from rpython.rlib.rbigint import rbigint -def test_copysign(): - assert copysign(1, 1) == 1 - assert copysign(-1, 1) == 1 - assert copysign(-1, -1) == -1 - assert copysign(1, -1) == -1 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit