[pypy-commit] pypy numpypy-complex2: some work on complex numbers
jbs
noreply at buildbot.pypy.org
Wed Jun 27 16:37:56 CEST 2012
Author: Jasper Schulz <jasper.schulz at student.hpi.uni-potsdam.de>
Branch: numpypy-complex2
Changeset: r55863:7623c78dccba
Date: 2012-06-27 16:34 +0200
http://bitbucket.org/pypy/pypy/changeset/7623c78dccba/
Log: some work on complex numbers
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -79,7 +79,9 @@
'unicode_': 'interp_boxes.W_UnicodeBox',
'void': 'interp_boxes.W_VoidBox',
'complexfloating': 'interp_boxes.W_ComplexFloatingBox',
- 'complex128': 'interp_boxes.W_Complex128Box'
+ 'complex_': 'interp_boxes.W_Complex128Box',
+ 'complex128': 'interp_boxes.W_Complex128Box',
+ 'complex64': 'interp_boxes.W_Complex64Box',
}
# ufuncs
@@ -94,6 +96,8 @@
("arccosh", "arccosh"),
("arcsinh", "arcsinh"),
("arctanh", "arctanh"),
+ ("conj", "conjugate"),
+ ("conjugate", "conjugate"),
("copysign", "copysign"),
("cos", "cos"),
("cosh", "cosh"),
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -34,6 +34,22 @@
def convert_to(self, dtype):
return dtype.box(self.value)
+class ComplexBox(object):
+ _mixin_ = True
+
+ def __init__(self, real, imag):
+ self.real = real
+ self.imag = imag
+
+ def descr_get_real(self, space):
+ return space.wrap(self._COMPONENTS_BOX(self.real))
+
+ def descr_get_imag(self, space):
+ return space.wrap(self._COMPONENTS_BOX(self.imag))
+
+ def convert_to(self, dtype):
+ return dtype.box_complex(self.real, self.imag)
+
class W_GenericBox(Wrappable):
_attrs_ = ()
@@ -274,19 +290,15 @@
class W_ComplexFloatingBox(W_InexactBox):
_attrs_ = ()
-class W_Complex128Box(W_ComplexFloatingBox):
+class W_Complex64Box(ComplexBox, W_ComplexFloatingBox):
+ descr__new__, _get_dtype = new_dtype_getter("complex64")
+ _COMPONENTS_BOX = W_Float32Box
+
+class W_Complex128Box(ComplexBox, W_ComplexFloatingBox):
descr__new__, _get_dtype = new_dtype_getter("complex128")
+ _COMPONENTS_BOX = W_Float64Box
- def __init__(self, real, imag):
- self.real = real
- self.imag = imag
-
- def descr_get_real(self, space):
- return space.wrap(self.real)
-
- def descr_get_imag(self, space):
- return space.wrap(self.imag)
-
+
W_GenericBox.typedef = TypeDef("generic",
__module__ = "numpypy",
@@ -474,9 +486,17 @@
__module__ = "numpypy",
)
+
W_Complex128Box.typedef = TypeDef("complex128", (W_ComplexFloatingBox.typedef, complex_typedef),
__module__ = "numpypy",
__new__ = interp2app(W_Complex128Box.descr__new__.im_func),
real = GetSetProperty(W_Complex128Box.descr_get_real),
imag = GetSetProperty(W_Complex128Box.descr_get_imag),
+)
+
+W_Complex64Box.typedef = TypeDef("complex64", (W_ComplexFloatingBox.typedef),
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Complex64Box.descr__new__.im_func),
+ real = GetSetProperty(W_Complex64Box.descr_get_real),
+ imag = GetSetProperty(W_Complex64Box.descr_get_imag),
)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -40,6 +40,11 @@
def box(self, value):
return self.itemtype.box(value)
+ @specialize.argtype(1, 2)
+ def box_complex(self, real, imag):
+ return self.itemtype.box_complex(real, imag)
+
+
def coerce(self, space, w_item):
return self.itemtype.coerce(space, self, w_item)
@@ -387,12 +392,27 @@
alternate_constructors=[space.w_float],
aliases=["float"],
)
+ # self.w_float128dtype = W_Dtype(
+ # types.Float128(),
+ # num=13,
+ # kind=FLOATINGLTR,
+ # name="float128",
+ # ...
+ # )
+ self.w_complex64dtype = W_Dtype(
+ types.Complex64(),
+ num=14,
+ kind=FLOATINGLTR,
+ name="complex64",
+ char="F",
+ w_box_type = space.gettypefor(interp_boxes.W_Complex64Box),
+ )
self.w_complex128dtype = W_Dtype(
types.Complex128(),
num=15,
kind=FLOATINGLTR,
name="complex128",
- char="c",
+ char="D",
w_box_type = space.gettypefor(interp_boxes.W_Complex128Box),
alternate_constructors=[space.w_complex],
aliases=["complex"],
@@ -430,7 +450,8 @@
self.w_int16dtype, self.w_uint16dtype, self.w_int32dtype,
self.w_uint32dtype, self.w_longdtype, self.w_ulongdtype,
self.w_int64dtype, self.w_uint64dtype,
- self.w_float32dtype, self.w_float64dtype, self.w_complex128dtype,
+ self.w_float32dtype, self.w_float64dtype, self.w_complex64dtype,
+ self.w_complex128dtype,
self.w_stringdtype, self.w_unicodedtype,
self.w_voiddtype,
]
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -443,6 +443,7 @@
bool_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
long_dtype = interp_dtype.get_dtype_cache(space).w_longdtype
int64_dtype = interp_dtype.get_dtype_cache(space).w_int64dtype
+ complex_type = interp_dtype.get_dtype_cache(space).w_complex128dtype
if isinstance(w_obj, interp_boxes.W_GenericBox):
dtype = w_obj.get_dtype(space)
@@ -464,6 +465,13 @@
current_guess is long_dtype or current_guess is int64_dtype):
return int64_dtype
return current_guess
+ elif space.isinstance_w(w_obj, space.w_complex):
+ if (current_guess is None or current_guess is bool_dtype or
+ current_guess is long_dtype or current_guess is int64_dtype or
+ current_guess is complex_type):
+ return complex_type
+ return current_guess
+
return interp_dtype.get_dtype_cache(space).w_float64dtype
@@ -535,6 +543,7 @@
("sign", "sign", 1, {"promote_bools": True}),
("signbit", "signbit", 1, {"bool_result": True}),
("reciprocal", "reciprocal", 1),
+ ("conjugate", "conj", 1),
("fabs", "fabs", 1, {"promote_to_float": True}),
("fmax", "fmax", 2, {"promote_to_float": True}),
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -427,29 +427,56 @@
assert numpy.complexfloating.__mro__ == (numpy.complexfloating,
numpy.inexact, numpy.number, numpy.generic, object)
+ def test_complex_format(self):
+ import _numpypy as numpy
+
+ for complex_ in (numpy.complex128, numpy.complex64,):
+ for real, imag, should in [
+ (1, 2, '(1+2j)'),
+ (0, 1, '1j'),
+ (1, 0, '(1+0j)'),
+ (-1, -2, '(-1-2j)'),
+ (0.5, -0.75, '(0.5-0.75j)'),
+ #xxx
+ #(numpy.inf, numpy.inf, '(inf+inf*j)'),
+ ]:
+
+ c = complex_(complex(real, imag))
+ assert c == complex(real, imag)
+ assert c.real == real
+ assert c.imag == imag
+ assert repr(c) == should
+
+ real, imag, should = (1e100, 3e66, '(1e+100+3e+66j)')
+ c128 = numpy.complex128(complex(real, imag))
+ assert type(c128.real) is type(c128.imag) is numpy.float64
+ assert c128.real == real
+ assert c128.imag == imag
+ assert repr(c128) == should
+
+ c64 = numpy.complex64(complex(real, imag))
+ assert repr(c64.real) == 'inf'
+ assert type(c64.real) is type(c64.imag) is numpy.float32
+ assert repr(c64.imag).startswith('inf')
+ assert repr(c64) in ('(inf+inf*j)', '(inf+infj)')
+
+
+ assert numpy.complex128(1.2) == numpy.complex128(complex(1.2, 0))
+ assert numpy.complex64(1.2) == numpy.complex64(complex(1.2, 0))
+
def test_complex(self):
import _numpypy as numpy
+ assert numpy.complex_ is numpy.complex128
+ assert numpy.complex64.__mro__ == (numpy.complex64,
+ numpy.complexfloating, numpy.inexact, numpy.number, numpy.generic,
+ object)
assert numpy.complex128.__mro__ == (numpy.complex128,
numpy.complexfloating, numpy.inexact, numpy.number, numpy.generic,
complex, object)
- for real, imag, should in [
- (1, 2, '(1+2j)'),
- (0, 1, '1j'),
- (1, 0, '(1+0j)'),
- (-1, -2, '(-1-2j)')
- ]:
-
- c = numpy.complex128(complex(real, imag))
- assert c.real == real
- assert c.imag == imag
- assert repr(c) == should
-
- def test_complex_dtype(self):
- import _numpypy as numpy
-
- assert numpy.dtype(complex) is numpy.dtype("complex")
+ assert numpy.dtype(complex).type is numpy.complex128
+ assert numpy.dtype("complex").type is numpy.complex128
def test_subclass_type(self):
import _numpypy as numpy
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -823,3 +823,88 @@
assert logaddexp2(float('-inf'), float('inf')) == float('inf')
assert logaddexp2(float('inf'), float('-inf')) == float('inf')
assert logaddexp2(float('inf'), float('inf')) == float('inf')
+
+ def test_conjugate(self):
+ from _numpypy import conj, conjugate, complex128, complex64
+ import _numpypy as np
+
+ c0 = complex128(complex(2.5, 0))
+ c1 = complex64(complex(1, 2))
+
+ assert conj is conjugate
+ assert conj(c0) == c0
+ assert conj(c1) == complex(1, -2)
+ assert conj(1) == 1
+ assert conj(-3) == -3
+ assert conj(float('-inf')) == float('-inf')
+
+
+ assert np.conjugate(1+2j) == 1-2j
+
+ x = np.eye(2) + 1j * np.eye(2)
+ for a, b in zip(np.conjugate(x), np.array([[ 1.-1.j, 0.-0.j], [ 0.-0.j, 1.-1.j]])):
+ assert a[0] == b[0]
+ assert a[1] == b[1]
+
+
+ def test_complex(self):
+ from _numpypy import (array, complex128, complex64, add, subtract as sub, multiply,
+ divide, negative, conjugate, conj, abs)
+ from _numpypy import equal, not_equal, greater, greater_equal, less, less_equal
+
+ for complex_ in complex128, complex64:
+
+ O = complex(0, 0)
+ c0 = complex_(complex(2.5, 0))
+ c1 = complex_(complex(1, 2))
+ c2 = complex_(complex(3, 4))
+ c3 = complex_(complex(-3, -3))
+
+ assert equal(c0, 2.5)
+ assert equal(c1, complex_(complex(1, 2)))
+ assert equal(c1, complex(1, 2))
+ assert equal(c1, c1)
+ assert not_equal(c1, c2)
+ assert not equal(c1, c2)
+
+ assert less(c1, c2)
+ assert less_equal(c1, c2)
+ assert less_equal(c1, c1)
+ assert not less(c1, c1)
+
+ assert greater(c2, c1)
+ assert greater_equal(c2, c1)
+ assert not greater(c1, c2)
+
+ assert add(c1, c2) == complex_(complex(4, 6))
+ assert add(c1, c2) == complex(4, 6)
+
+ assert sub(c0, c0) == sub(c1, c1) == 0
+ assert sub(c1, c2) == complex(-2, -2)
+ assert negative(complex(1,1)) == complex(-1, -1)
+ assert negative(complex(0, 0)) == 0
+
+
+ assert multiply(1, c1) == c1
+ assert multiply(2, c2) == complex(6, 8)
+ assert multiply(c1, c2) == complex(-5, 10)
+
+ assert divide(c0, 1) == c0
+ assert divide(c2, -1) == negative(c2)
+ assert divide(c1, complex(0, 1)) == complex(2, -1)
+ n = divide(c1, O)
+ assert repr(n.real) == 'nan'
+ assert repr(n.imag).startswith('nan') #can be nan*j or nanj
+ assert divide(c0, c0) == 1
+ res = divide(c2, c1)
+ assert abs(res.real-2.2) < 0.001
+ assert abs(res.imag+0.4) < 0.001
+
+ assert abs(c0) == 2.5
+ assert abs(c2) == 5
+
+
+
+ def test_complex_math(self):
+ # from _numpypy import
+ pass
\ No newline at end of file
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
@@ -6,13 +6,14 @@
from pypy.module.micronumpy import interp_boxes
from pypy.objspace.std.floatobject import float2string
from pypy.objspace.std.complexobject import W_ComplexObject, str_format
-from pypy.rlib import rfloat, libffi, clibffi
+from pypy.rlib import rfloat, libffi, clibffi, rcomplex
from pypy.rlib.objectmodel import specialize, we_are_translated
from pypy.rlib.rarithmetic import widen, byteswap
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rlib.rstruct.runpack import runpack
from pypy.tool.sourcetools import func_with_new_name
from pypy.rlib import jit
+from pypy.module import cmath
VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True,
@@ -34,6 +35,18 @@
)
return dispatcher
+def complex_unary_op(func):
+ specialize.argtype(1)(func)
+ @functools.wraps(func)
+ def dispatcher(self, v):
+ return self.box_complex(
+ *func(
+ self,
+ self.for_computation(self.unbox(v))
+ )
+ )
+ return dispatcher
+
def raw_unary_op(func):
specialize.argtype(1)(func)
@functools.wraps(func)
@@ -57,6 +70,19 @@
)
return dispatcher
+def complex_binary_op(func):
+ specialize.argtype(1, 2)(func)
+ @functools.wraps(func)
+ def dispatcher(self, v1, v2):
+ return self.box_complex(
+ *func(
+ self,
+ self.for_computation(self.unbox(v1)),
+ self.for_computation(self.unbox(v2)),
+ )
+ )
+ return dispatcher
+
def raw_binary_op(func):
specialize.argtype(1, 2)(func)
@functools.wraps(func)
@@ -173,6 +199,10 @@
return -v
@simple_unary_op
+ def conj(self, v):
+ return v
+
+ @simple_unary_op
def abs(self, v):
return abs(v)
@@ -919,33 +949,464 @@
BoxType = interp_boxes.W_Float64Box
format_code = "d"
-class Complex128(BaseType):
+class ComplexFloating(object):
+ _mixin_ = True
+ _attrs_ = ()
+
+ def _coerce(self, space, w_item):
+ w_item = space.call_function(space.w_complex, w_item)
+ real, imag = space.unpackcomplex(w_item)
+ return self.box_complex(real, imag)
+
+ def coerce(self, space, dtype, w_item):
+ if isinstance(w_item, self.BoxType):
+ return w_item
+ return self.coerce_subtype(space, space.gettypefor(self.BoxType), w_item)
+
+ def coerce_subtype(self, space, w_subtype, w_item):
+ w_tmpobj = self._coerce(space, w_item)
+ w_obj = space.allocate_instance(self.BoxType, w_subtype)
+ assert isinstance(w_obj, self.BoxType)
+ w_obj.__init__(w_tmpobj.real, w_tmpobj.imag)
+ return w_obj
+
+ def str_format(self, box):
+ real, imag = self.for_computation(self.unbox(box))
+ imag_str = str_format(imag) + 'j'
+
+ # (0+2j) => 2j
+ if real == 0:
+ return imag_str
+
+ real_str = str_format(real)
+ op = '+' if imag >= 0 else ''
+ return ''.join(['(', real_str, op, imag_str, ')'])
+
+ def for_computation(self, v):
+ return float(v[0]), float(v[1])
+
+ def get_element_size(self):
+ return 2 * rffi.sizeof(self._COMPONENTS_T)
+
+ @specialize.argtype(1)
+ def box(self, value):
+ return self.BoxType(
+ rffi.cast(self._COMPONENTS_T, value),
+ rffi.cast(self._COMPONENTS_T, 0.0))
+
+ @specialize.argtype(1, 2)
+ def box_complex(self, real, imag):
+ return self.BoxType(
+ rffi.cast(self._COMPONENTS_T, real),
+ rffi.cast(self._COMPONENTS_T, imag))
+
+ def unbox(self, box):
+ assert isinstance(box, self.BoxType)
+ return box.real, box.imag
+
+ @complex_binary_op
+ def add(self, v1, v2):
+ return rcomplex.c_add(v1, v2)
+
+ @complex_binary_op
+ def sub(self, v1, v2):
+ return rcomplex.c_sub(v1, v2)
+
+ @complex_binary_op
+ def mul(self, v1, v2):
+ return rcomplex.c_mul(v1, v2)
+
+ @complex_binary_op
+ def div(self, v1, v2):
+ try:
+ return rcomplex.c_div(v1, v2)
+ except ZeroDivisionError:
+ return rfloat.NAN, rfloat.NAN
+
+
+
+ @complex_unary_op
+ def pos(self, v):
+ return v
+
+ @complex_unary_op
+ def neg(self, v):
+ return -v[0], -v[1]
+
+ @complex_unary_op
+ def conj(self, v):
+ return v[0], -v[1]
+
+ @raw_unary_op
+ def abs(self, v):
+ return rcomplex.c_abs(v[0], v[1])
+
+ @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])
+
+ @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])
+
+ def _eq(self, v1, v2):
+ return v1[0] == v2[0] and v1[1] == v2[1]
+
+ @raw_binary_op
+ def eq(self, v1, v2):
+ #compare the parts, so nan == nan is False
+ return self._eq(v1, v2)
+
+ @raw_binary_op
+ def ne(self, v1, v2):
+ return not self._eq(v1, v2)
+
+ def _lt(self, v1, v2):
+ (r1, i1), (r2, i2) = v1, v2
+ if r1 < r2:
+ return True
+ elif not r1 <= r2:
+ return False
+ return i1 < i2
+
+ @raw_binary_op
+ def lt(self, v1, v2):
+ return self._lt(v1, v2)
+
+ @raw_binary_op
+ def le(self, v1, v2):
+ return self._lt(v1, v2) or self._eq(v1, v2)
+
+ @raw_binary_op
+ def gt(self, v1, v2):
+ return self._lt(v2, v1)
+
+ @raw_binary_op
+ def ge(self, v1, v2):
+ return self._lt(v2, v1) or self._eq(v2, v1)
+
+ @raw_binary_op
+ def logical_and(self, v1, v2):
+ return bool(v1) and bool(v2)
+
+ @raw_binary_op
+ def logical_or(self, v1, v2):
+ return bool(v1) or bool(v2)
+
+ @raw_unary_op
+ def logical_not(self, v):
+ return not bool(v)
+
+ @raw_binary_op
+ def logical_xor(self, v1, v2):
+ return bool(v1) ^ bool(v2)
+
+ def bool(self, v):
+ return bool(self.for_computation(self.unbox(v)))
+
+ @simple_binary_op
+ def max(self, v1, v2):
+ return max(v1, v2)
+
+ @simple_binary_op
+ def min(self, v1, v2):
+ return min(v1, v2)
+
+
+ @simple_binary_op
+ def floordiv(self, v1, v2):
+ try:
+ r, i = rcomplex.c_div(v1, v2)
+ return math.floor(r), 0
+ except ZeroDivisionError:
+ return rfloat.NAN, 0
+
+ @simple_binary_op
+ def mod(self, v1, v2):
+ return math.fmod(v1, v2)
+
+ @simple_binary_op
+ def pow(self, v1, v2):
+ try:
+ return math.pow(v1, v2)
+ except ValueError:
+ return rfloat.NAN
+ 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 rfloat.INFINITY
+
+ @simple_binary_op
+ def copysign(self, v1, v2):
+ return math.copysign(v1, v2)
+
+ @simple_unary_op
+ def sign(self, v):
+ if v == 0.0:
+ return 0.0
+ return rfloat.copysign(1.0, v)
+
+ @raw_unary_op
+ def signbit(self, v):
+ return rfloat.copysign(1.0, v) < 0.0
+
+ @simple_unary_op
+ def fabs(self, v):
+ return math.fabs(v)
+
+ @simple_binary_op
+ def fmax(self, v1, v2):
+ if math.isnan(v1):
+ return v1
+ elif math.isnan(v2):
+ return v2
+ return max(v1, v2)
+
+ @simple_binary_op
+ def fmin(self, v1, v2):
+ if math.isnan(v1):
+ return v1
+ elif math.isnan(v2):
+ return v2
+ return min(v1, v2)
+
+ @simple_binary_op
+ def fmod(self, v1, v2):
+ try:
+ return math.fmod(v1, v2)
+ except ValueError:
+ return rfloat.NAN
+
+ @simple_unary_op
+ def reciprocal(self, v):
+ if v == 0.0:
+ return rfloat.copysign(rfloat.INFINITY, v)
+ return 1.0 / v
+
+ @simple_unary_op
+ def floor(self, v):
+ return math.floor(v)
+
+ @simple_unary_op
+ def ceil(self, v):
+ return math.ceil(v)
+
+ @simple_unary_op
+ def trunc(self, v):
+ if v < 0:
+ return math.ceil(v)
+ else:
+ return math.floor(v)
+
+ @simple_unary_op
+ def exp(self, v):
+ try:
+ return math.exp(v)
+ except OverflowError:
+ return rfloat.INFINITY
+
+ @simple_unary_op
+ def exp2(self, v):
+ try:
+ return math.pow(2, v)
+ except OverflowError:
+ return rfloat.INFINITY
+
+ @simple_unary_op
+ def expm1(self, v):
+ try:
+ return rfloat.expm1(v)
+ except OverflowError:
+ return rfloat.INFINITY
+
+ @simple_unary_op
+ def sin(self, v):
+ return math.sin(v)
+
+ @simple_unary_op
+ def cos(self, v):
+ return math.cos(v)
+
+ @simple_unary_op
+ def tan(self, v):
+ return math.tan(v)
+
+ @simple_unary_op
+ def arcsin(self, v):
+ if not -1.0 <= v <= 1.0:
+ return rfloat.NAN
+ return math.asin(v)
+
+ @simple_unary_op
+ def arccos(self, v):
+ if not -1.0 <= v <= 1.0:
+ return rfloat.NAN
+ return math.acos(v)
+
+ @simple_unary_op
+ def arctan(self, v):
+ return math.atan(v)
+
+ @simple_binary_op
+ def arctan2(self, v1, v2):
+ return math.atan2(v1, v2)
+
+ @simple_unary_op
+ def sinh(self, v):
+ return math.sinh(v)
+
+ @simple_unary_op
+ def cosh(self, v):
+ return math.cosh(v)
+
+ @simple_unary_op
+ def tanh(self, v):
+ return math.tanh(v)
+
+ @simple_unary_op
+ def arcsinh(self, v):
+ return math.asinh(v)
+
+ @simple_unary_op
+ def arccosh(self, v):
+ if v < 1.0:
+ return rfloat.NAN
+ return math.acosh(v)
+
+ @simple_unary_op
+ def arctanh(self, v):
+ if v == 1.0 or v == -1.0:
+ return math.copysign(rfloat.INFINITY, v)
+ if not -1.0 < v < 1.0:
+ return rfloat.NAN
+ return math.atanh(v)
+
+ @simple_unary_op
+ def sqrt(self, v):
+ try:
+ return math.sqrt(v)
+ except ValueError:
+ return rfloat.NAN
+
+ @simple_unary_op
+ def square(self, v):
+ return v*v
+
+ @raw_unary_op
+ def isnan(self, v):
+ return rfloat.isnan(v)
+
+ @raw_unary_op
+ def isinf(self, v):
+ return rfloat.isinf(v)
+
+ @raw_unary_op
+ def isneginf(self, v):
+ return rfloat.isinf(v) and v < 0
+
+ @raw_unary_op
+ def isposinf(self, v):
+ return rfloat.isinf(v) and v > 0
+
+ @raw_unary_op
+ def isfinite(self, v):
+ return not (rfloat.isinf(v) or rfloat.isnan(v))
+
+ @simple_unary_op
+ def radians(self, v):
+ return v * degToRad
+ deg2rad = radians
+
+ @simple_unary_op
+ def degrees(self, v):
+ return v / degToRad
+
+ @simple_unary_op
+ def log(self, v):
+ try:
+ return math.log(v)
+ except ValueError:
+ if v == 0.0:
+ # CPython raises ValueError here, so we have to check
+ # the value to find the correct numpy return value
+ return -rfloat.INFINITY
+ return rfloat.NAN
+
+ @simple_unary_op
+ def log2(self, v):
+ try:
+ return math.log(v) / log2
+ except ValueError:
+ if v == 0.0:
+ # CPython raises ValueError here, so we have to check
+ # the value to find the correct numpy return value
+ return -rfloat.INFINITY
+ return rfloat.NAN
+
+ @simple_unary_op
+ def log10(self, v):
+ try:
+ return math.log10(v)
+ except ValueError:
+ if v == 0.0:
+ # CPython raises ValueError here, so we have to check
+ # the value to find the correct numpy return value
+ return -rfloat.INFINITY
+ return rfloat.NAN
+
+ @simple_unary_op
+ def log1p(self, v):
+ try:
+ return rfloat.log1p(v)
+ except OverflowError:
+ return -rfloat.INFINITY
+ except ValueError:
+ return rfloat.NAN
+
+ @simple_binary_op
+ def logaddexp(self, v1, v2):
+ tmp = v1 - v2
+ if tmp > 0:
+ return v1 + rfloat.log1p(math.exp(-tmp))
+ elif tmp <= 0:
+ return v2 + rfloat.log1p(math.exp(tmp))
+ else:
+ return v1 + v2
+
+ def npy_log2_1p(self, v):
+ return log2e * rfloat.log1p(v)
+
+ @simple_binary_op
+ def logaddexp2(self, v1, v2):
+ tmp = v1 - v2
+ if tmp > 0:
+ return v1 + self.npy_log2_1p(math.pow(2, -tmp))
+ if tmp <= 0:
+ return v2 + self.npy_log2_1p(math.pow(2, tmp))
+ else:
+ return v1 + v2
+
+class Complex64(ComplexFloating, BaseType):
_attrs_ = ()
T = rffi.CHAR
+ _COMPONENTS_T = rffi.FLOAT
+ BoxType = interp_boxes.W_Complex64Box
+
+
+
+NonNativeComplex64 = Complex64
+
+class Complex128(ComplexFloating, BaseType):
+ _attrs_ = ()
+
+ T = rffi.CHAR
+ _COMPONENTS_T = rffi.DOUBLE
BoxType = interp_boxes.W_Complex128Box
- def get_element_size(self):
- return 2 * rffi.sizeof(rffi.DOUBLE)
-
- def coerce_subtype(self, space, w_subtype, w_item):
- real, imag = space.unpackcomplex(w_item)
- w_obj = space.allocate_instance(self.BoxType, w_subtype)
- assert isinstance(w_obj, self.BoxType)
- w_obj.__init__(real, imag)
- return w_obj
-
- def str_format(self, box):
- imag_str = str_format(box.imag) + 'j'
-
- # (0+2j) => 2j
- if box.real == 0:
- return imag_str
-
- real_str = str_format(box.real)
- op = '+' if box.imag >= 0 else ''
- return ''.join(['(', real_str, op, imag_str, ')'])
-
NonNativeComplex128 = Complex128
More information about the pypy-commit
mailing list