[pypy-commit] pypy can_cast: Implement enough of can_cast(<value>, dtype) to pass the test

rlamy noreply at buildbot.pypy.org
Mon Apr 27 06:44:46 CEST 2015


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: can_cast
Changeset: r76945:d45abfb9685d
Date: 2015-04-27 05:44 +0100
http://bitbucket.org/pypy/pypy/changeset/d45abfb9685d/

Log:	Implement enough of can_cast(<value>, dtype) to pass the test

diff --git a/pypy/module/micronumpy/arrayops.py b/pypy/module/micronumpy/arrayops.py
--- a/pypy/module/micronumpy/arrayops.py
+++ b/pypy/module/micronumpy/arrayops.py
@@ -10,6 +10,7 @@
 from .boxes import W_GenericBox
 from .types import (
     Bool, ULong, Long, Float64, Complex64, UnicodeType, VoidType, ObjectType)
+from .descriptor import get_dtype_cache
 
 
 def where(space, w_arr, w_x=None, w_y=None):
@@ -360,7 +361,11 @@
         return can_cast_type(space, from_type, target, casting)
     if not from_type.is_native():
         value = value.descr_byteswap(space)
-    return can_cast_type(space, from_type, target, casting)  # XXX: stub impl
+    dtypenum, altnum = value.min_dtype()
+    if target.is_unsigned():
+        dtypenum = altnum
+    dtype = get_dtype_cache(space).dtypes_by_num[dtypenum]
+    return can_cast_type(space, dtype, target, casting)  # XXX: stub impl
 
 def is_scalar_w(space, w_arg):
     return (isinstance(w_arg, W_GenericBox) or
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -874,4 +874,3 @@
     __new__ = interp2app(W_ObjectBox.descr__new__.im_func),
     __getattr__ = interp2app(W_ObjectBox.descr__getattr__),
 )
-
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
@@ -1,5 +1,6 @@
 import functools
 import math
+from rpython.rlib.unroll import unrolling_iterable
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.objspace.std.floatobject import float2string
 from pypy.objspace.std.complexobject import str_format
@@ -2472,3 +2473,56 @@
     for tp2 in complex_types:
         if tp1.basesize() <= tp2.basesize():
             enable_cast(tp1, tp2)
+
+_int_types = [(Int8, UInt8), (Int16, UInt16), (Int32, UInt32),
+        (Int64, UInt64), (Long, ULong)]
+for Int_t, UInt_t in _int_types:
+    Int_t.Unsigned = UInt_t
+    UInt_t.Signed = Int_t
+    size = rffi.sizeof(Int_t.T)
+    Int_t.min_value = rffi.cast(Int_t.T, -1) << (8*size - 1)
+    Int_t.max_value = ~Int_t.min_value
+    UInt_t.max_value = ~rffi.cast(UInt_t.T, 0)
+
+
+signed_types = [Int8, Int16, Int32, Int64, Long]
+
+for Int_t in signed_types:
+    UInt_t = Int_t.Unsigned
+    smaller_types = [tp for tp in signed_types
+            if rffi.sizeof(tp.T) < rffi.sizeof(Int_t.T)]
+    smaller_types = unrolling_iterable(
+            [(tp, tp.Unsigned) for tp in smaller_types])
+    def min_dtype(self):
+        for Small, USmall in smaller_types:
+            signed_max = rffi.cast(UInt_t.T, Small.max_value)
+            unsigned_max = rffi.cast(UInt_t.T, USmall.max_value)
+            if self.value <= unsigned_max:
+                if self.value <= signed_max:
+                    return Small.num, USmall.num
+                else:
+                    return USmall.num, USmall.num
+        if self.value <= rffi.cast(UInt_t.T, Int_t.max_value):
+            return Int_t.num, UInt_t.num
+        else:
+            return UInt_t.num, UInt_t.num
+    UInt_t.BoxType.min_dtype = min_dtype
+
+    def min_dtype(self):
+        if self.value >= 0:
+            for Small, USmall in smaller_types:
+                signed_max = rffi.cast(UInt_t.T, Small.max_value)
+                unsigned_max = rffi.cast(UInt_t.T, USmall.max_value)
+                if self.value <= unsigned_max:
+                    if self.value <= signed_max:
+                        return Small.num, USmall.num
+                    else:
+                        return USmall.num, USmall.num
+            return Int_t.num, UInt_t.num
+        else:
+            for Small, USmall in smaller_types:
+                signed_min = rffi.cast(UInt_t.T, Small.min_value)
+                if self.value >= signed_max:
+                        return Small.num, Small.num
+            return Int_t.num, Int_t.num
+    Int_t.BoxType.min_dtype = min_dtype


More information about the pypy-commit mailing list