[pypy-commit] pypy win64-stage1: Merge with default
ctismer
noreply at buildbot.pypy.org
Sun Dec 4 01:23:41 CET 2011
Author: Christian Tismer <tismer at stackless.com>
Branch: win64-stage1
Changeset: r50101:e7ab064d5412
Date: 2011-12-04 01:22 +0100
http://bitbucket.org/pypy/pypy/changeset/e7ab064d5412/
Log: Merge with default
diff --git a/lib_pypy/itertools.py b/lib_pypy/_itertools.py
copy from lib_pypy/itertools.py
copy to lib_pypy/_itertools.py
--- a/lib_pypy/itertools.py
+++ b/lib_pypy/_itertools.py
@@ -1,5 +1,5 @@
-# Note that PyPy contains also a built-in module 'itertools' which will
-# hide this one if compiled in.
+# Note that PyPy contains also a built-in implementation of 'itertools';
+# when translated with default options, this one is not used.
"""Functional tools for creating and using iterators.
@@ -25,7 +25,7 @@
__all__ = ['chain', 'count', 'cycle', 'dropwhile', 'groupby', 'ifilter',
'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
- 'takewhile', 'tee']
+ 'takewhile', 'tee', 'compress', 'product']
try: from __pypy__ import builtinify
except ImportError: builtinify = lambda f: f
diff --git a/lib_pypy/itertools.py b/lib_pypy/itertools.py
--- a/lib_pypy/itertools.py
+++ b/lib_pypy/itertools.py
@@ -1,670 +1,6 @@
-# Note that PyPy contains also a built-in module 'itertools' which will
-# hide this one if compiled in.
-
-"""Functional tools for creating and using iterators.
-
-Infinite iterators:
-count([n]) --> n, n+1, n+2, ...
-cycle(p) --> p0, p1, ... plast, p0, p1, ...
-repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times
-
-Iterators terminating on the shortest input sequence:
-izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ...
-ifilter(pred, seq) --> elements of seq where pred(elem) is True
-ifilterfalse(pred, seq) --> elements of seq where pred(elem) is False
-islice(seq, [start,] stop [, step]) --> elements from
- seq[start:stop:step]
-imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...
-starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...
-tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n
-chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...
-takewhile(pred, seq) --> seq[0], seq[1], until pred fails
-dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails
-groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)
-"""
-
-__all__ = ['chain', 'count', 'cycle', 'dropwhile', 'groupby', 'ifilter',
- 'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
- 'takewhile', 'tee']
-
-try: from __pypy__ import builtinify
-except ImportError: builtinify = lambda f: f
-
-
-class chain(object):
- """Make an iterator that returns elements from the first iterable
- until it is exhausted, then proceeds to the next iterable, until
- all of the iterables are exhausted. Used for treating consecutive
- sequences as a single sequence.
-
- Equivalent to :
-
- def chain(*iterables):
- for it in iterables:
- for element in it:
- yield element
- """
- def __init__(self, *iterables):
- self._iterables_iter = iter(map(iter, iterables))
- # little trick for the first chain.next() call
- self._cur_iterable_iter = iter([])
-
- def __iter__(self):
- return self
-
- def next(self):
- while True:
- try:
- return self._cur_iterable_iter.next()
- except StopIteration:
- self._cur_iterable_iter = self._iterables_iter.next()
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % \
- (self._cur_iterable_iter))
-
-
-class compress(object):
- def __init__(self, data, selectors):
- self.data = iter(data)
- self.selectors = iter(selectors)
-
- def __iter__(self):
- return self
-
- def next(self):
- while True:
- next_item = self.data.next()
- next_selector = self.selectors.next()
- if bool(next_selector):
- return next_item
-
-
-class count(object):
- """Make an iterator that returns consecutive integers starting
- with n. If not specified n defaults to zero. Does not currently
- support python long integers. Often used as an argument to imap()
- to generate consecutive data points. Also, used with izip() to
- add sequence numbers.
-
- Equivalent to :
-
- def count(n=0):
- if not isinstance(n, int):
- raise TypeError("%s is not a regular integer" % n)
- while True:
- yield n
- n += 1
- """
- def __init__(self, n=0):
- if not isinstance(n, int):
- raise TypeError('%s is not a regular integer' % n)
- self.times = n-1
-
- def __iter__(self):
- return self
-
- def next(self):
- self.times += 1
- return self.times
-
- def __repr__(self):
- return 'count(%d)' % (self.times + 1)
-
-
-
-class cycle(object):
- """Make an iterator returning elements from the iterable and
- saving a copy of each. When the iterable is exhausted, return
- elements from the saved copy. Repeats indefinitely.
-
- Equivalent to :
-
- def cycle(iterable):
- saved = []
- for element in iterable:
- yield element
- saved.append(element)
- while saved:
- for element in saved:
- yield element
- """
- def __init__(self, iterable):
- self._cur_iter = iter(iterable)
- self._saved = []
- self._must_save = True
-
- def __iter__(self):
- return self
-
- def next(self):
- # XXX Could probably be improved
- try:
- next_elt = self._cur_iter.next()
- if self._must_save:
- self._saved.append(next_elt)
- except StopIteration:
- self._cur_iter = iter(self._saved)
- next_elt = self._cur_iter.next()
- self._must_save = False
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % \
- (self._cur_iter))
- return next_elt
-
-
-class dropwhile(object):
- """Make an iterator that drops elements from the iterable as long
- as the predicate is true; afterwards, returns every
- element. Note, the iterator does not produce any output until the
- predicate is true, so it may have a lengthy start-up time.
-
- Equivalent to :
-
- def dropwhile(predicate, iterable):
- iterable = iter(iterable)
- for x in iterable:
- if not predicate(x):
- yield x
- break
- for x in iterable:
- yield x
- """
- def __init__(self, predicate, iterable):
- self._predicate = predicate
- self._iter = iter(iterable)
- self._dropped = False
-
- def __iter__(self):
- return self
-
- def next(self):
- try:
- value = self._iter.next()
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % \
- (self._iter))
- if self._dropped:
- return value
- while self._predicate(value):
- value = self._iter.next()
- self._dropped = True
- return value
-
-class groupby(object):
- """Make an iterator that returns consecutive keys and groups from the
- iterable. The key is a function computing a key value for each
- element. If not specified or is None, key defaults to an identity
- function and returns the element unchanged. Generally, the
- iterable needs to already be sorted on the same key function.
-
- The returned group is itself an iterator that shares the
- underlying iterable with groupby(). Because the source is shared,
- when the groupby object is advanced, the previous group is no
- longer visible. So, if that data is needed later, it should be
- stored as a list:
-
- groups = []
- uniquekeys = []
- for k, g in groupby(data, keyfunc):
- groups.append(list(g)) # Store group iterator as a list
- uniquekeys.append(k)
- """
- def __init__(self, iterable, key=None):
- if key is None:
- key = lambda x: x
- self.keyfunc = key
- self.it = iter(iterable)
- self.tgtkey = self.currkey = self.currvalue = xrange(0)
-
- def __iter__(self):
- return self
-
- def next(self):
- while self.currkey == self.tgtkey:
- try:
- self.currvalue = self.it.next() # Exit on StopIteration
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % \
- (self.it))
- self.currkey = self.keyfunc(self.currvalue)
- self.tgtkey = self.currkey
- return (self.currkey, self._grouper(self.tgtkey))
-
- def _grouper(self, tgtkey):
- while self.currkey == tgtkey:
- yield self.currvalue
- self.currvalue = self.it.next() # Exit on StopIteration
- self.currkey = self.keyfunc(self.currvalue)
-
-
-
-class _ifilter_base(object):
- """base class for ifilter and ifilterflase"""
- def __init__(self, predicate, iterable):
- # Make sure iterable *IS* iterable
- self._iter = iter(iterable)
- if predicate is None:
- self._predicate = bool
- else:
- self._predicate = predicate
-
- def __iter__(self):
- return self
-
-class ifilter(_ifilter_base):
- """Make an iterator that filters elements from iterable returning
- only those for which the predicate is True. If predicate is
- None, return the items that are true.
-
- Equivalent to :
-
- def ifilter:
- if predicate is None:
- predicate = bool
- for x in iterable:
- if predicate(x):
- yield x
- """
- def next(self):
- try:
- next_elt = self._iter.next()
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % \
- (self._iter))
- while True:
- if self._predicate(next_elt):
- return next_elt
- next_elt = self._iter.next()
-
-class ifilterfalse(_ifilter_base):
- """Make an iterator that filters elements from iterable returning
- only those for which the predicate is False. If predicate is
- None, return the items that are false.
-
- Equivalent to :
-
- def ifilterfalse(predicate, iterable):
- if predicate is None:
- predicate = bool
- for x in iterable:
- if not predicate(x):
- yield x
- """
- def next(self):
- try:
- next_elt = self._iter.next()
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % \
- (self._iter))
- while True:
- if not self._predicate(next_elt):
- return next_elt
- next_elt = self._iter.next()
-
-
-
-
-class imap(object):
- """Make an iterator that computes the function using arguments
- from each of the iterables. If function is set to None, then
- imap() returns the arguments as a tuple. Like map() but stops
- when the shortest iterable is exhausted instead of filling in
- None for shorter iterables. The reason for the difference is that
- infinite iterator arguments are typically an error for map()
- (because the output is fully evaluated) but represent a common
- and useful way of supplying arguments to imap().
-
- Equivalent to :
-
- def imap(function, *iterables):
- iterables = map(iter, iterables)
- while True:
- args = [i.next() for i in iterables]
- if function is None:
- yield tuple(args)
- else:
- yield function(*args)
-
- """
- def __init__(self, function, iterable, *other_iterables):
- self._func = function
- self._iters = map(iter, (iterable, ) + other_iterables)
-
- def __iter__(self):
- return self
-
- def next(self):
- try:
- args = [it.next() for it in self._iters]
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % \
- (it))
- if self._func is None:
- return tuple(args)
- else:
- return self._func(*args)
-
-
-
-class islice(object):
- """Make an iterator that returns selected elements from the
- iterable. If start is non-zero, then elements from the iterable
- are skipped until start is reached. Afterward, elements are
- returned consecutively unless step is set higher than one which
- results in items being skipped. If stop is None, then iteration
- continues until the iterator is exhausted, if at all; otherwise,
- it stops at the specified position. Unlike regular slicing,
- islice() does not support negative values for start, stop, or
- step. Can be used to extract related fields from data where the
- internal structure has been flattened (for example, a multi-line
- report may list a name field on every third line).
- """
- def __init__(self, iterable, *args):
- s = slice(*args)
- self.start, self.stop, self.step = s.start or 0, s.stop, s.step
- if not isinstance(self.start, (int, long)):
- raise ValueError("Start argument must be an integer")
- if self.stop is not None and not isinstance(self.stop, (int,long)):
- raise ValueError("Stop argument must be an integer or None")
- if self.step is None:
- self.step = 1
- if self.start<0 or (self.stop is not None and self.stop<0
- ) or self.step<=0:
- raise ValueError, "indices for islice() must be positive"
- self.it = iter(iterable)
- self.donext = None
- self.cnt = 0
-
- def __iter__(self):
- return self
-
- def next(self):
- if self.donext is None:
- try:
- self.donext = self.it.next
- except AttributeError:
- raise TypeError
- nextindex = self.start
- if self.stop is not None and nextindex >= self.stop:
- raise StopIteration
- while self.cnt <= nextindex:
- nextitem = self.donext()
- self.cnt += 1
- self.start += self.step
- return nextitem
-
-class izip(object):
- """Make an iterator that aggregates elements from each of the
- iterables. Like zip() except that it returns an iterator instead
- of a list. Used for lock-step iteration over several iterables at
- a time.
-
- Equivalent to :
-
- def izip(*iterables):
- iterables = map(iter, iterables)
- while iterables:
- result = [i.next() for i in iterables]
- yield tuple(result)
- """
- def __init__(self, *iterables):
- self._iterators = map(iter, iterables)
- self._result = [None] * len(self._iterators)
-
- def __iter__(self):
- return self
-
- def next(self):
- if not self._iterators:
- raise StopIteration()
- try:
- return tuple([i.next() for i in self._iterators])
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % (i))
-
-
-class product(object):
-
- def __init__(self, *args, **kw):
- if len(kw) > 1:
- raise TypeError("product() takes at most 1 argument (%d given)" %
- len(kw))
- self.repeat = kw.get('repeat', 1)
- self.gears = [x for x in args] * self.repeat
- self.num_gears = len(self.gears)
- # initialization of indicies to loop over
- self.indicies = [(0, len(self.gears[x]))
- for x in range(0, self.num_gears)]
- self.cont = True
-
- def roll_gears(self):
- # Starting from the end of the gear indicies work to the front
- # incrementing the gear until the limit is reached. When the limit
- # is reached carry operation to the next gear
- should_carry = True
- for n in range(0, self.num_gears):
- nth_gear = self.num_gears - n - 1
- if should_carry:
- count, lim = self.indicies[nth_gear]
- count += 1
- if count == lim and nth_gear == 0:
- self.cont = False
- if count == lim:
- should_carry = True
- count = 0
- else:
- should_carry = False
- self.indicies[nth_gear] = (count, lim)
- else:
- break
-
- def __iter__(self):
- return self
-
- def next(self):
- if not self.cont:
- raise StopIteration
- l = []
- for x in range(0, self.num_gears):
- index, limit = self.indicies[x]
- l.append(self.gears[x][index])
- self.roll_gears()
- return tuple(l)
-
-
-class repeat(object):
- """Make an iterator that returns object over and over again.
- Runs indefinitely unless the times argument is specified. Used
- as argument to imap() for invariant parameters to the called
- function. Also used with izip() to create an invariant part of a
- tuple record.
-
- Equivalent to :
-
- def repeat(object, times=None):
- if times is None:
- while True:
- yield object
- else:
- for i in xrange(times):
- yield object
- """
- def __init__(self, obj, times=None):
- self._obj = obj
- if times is not None:
- xrange(times) # Raise a TypeError
- if times < 0:
- times = 0
- self._times = times
-
- def __iter__(self):
- return self
-
- def next(self):
- # next() *need* to decrement self._times when consumed
- if self._times is not None:
- if self._times <= 0:
- raise StopIteration()
- self._times -= 1
- return self._obj
-
- def __repr__(self):
- if self._times is not None:
- return 'repeat(%r, %r)' % (self._obj, self._times)
- else:
- return 'repeat(%r)' % (self._obj,)
-
- def __len__(self):
- if self._times == -1 or self._times is None:
- raise TypeError("len() of uniszed object")
- return self._times
-
-
-class starmap(object):
- """Make an iterator that computes the function using arguments
- tuples obtained from the iterable. Used instead of imap() when
- argument parameters are already grouped in tuples from a single
- iterable (the data has been ``pre-zipped''). The difference
- between imap() and starmap() parallels the distinction between
- function(a,b) and function(*c).
-
- Equivalent to :
-
- def starmap(function, iterable):
- iterable = iter(iterable)
- while True:
- yield function(*iterable.next())
- """
- def __init__(self, function, iterable):
- self._func = function
- self._iter = iter(iterable)
-
- def __iter__(self):
- return self
-
- def next(self):
- # CPython raises a TypeError when the iterator doesn't return a tuple
- try:
- t = self._iter.next()
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % self._iter)
- if not isinstance(t, tuple):
- raise TypeError("iterator must return a tuple")
- return self._func(*t)
-
-
-
-class takewhile(object):
- """Make an iterator that returns elements from the iterable as
- long as the predicate is true.
-
- Equivalent to :
-
- def takewhile(predicate, iterable):
- for x in iterable:
- if predicate(x):
- yield x
- else:
- break
- """
- def __init__(self, predicate, iterable):
- self._predicate = predicate
- self._iter = iter(iterable)
-
- def __iter__(self):
- return self
-
- def next(self):
- try:
- value = self._iter.next()
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % \
- (self._iter))
- if not self._predicate(value):
- raise StopIteration()
- return value
-
-
-class TeeData(object):
- """Holds cached values for TeeObjects"""
- def __init__(self, iterator):
- self.data = []
- self._iter = iterator
-
- def __getitem__(self, i):
- # iterates until 'i' if not done yet
- while i>= len(self.data):
- try:
- self.data.append( self._iter.next() )
- except AttributeError:
- # CPython raises a TypeError when next() is not defined
- raise TypeError('%s has no next() method' % self._iter)
- return self.data[i]
-
-
-class TeeObject(object):
- """Iterables / Iterators as returned by the tee() function"""
- def __init__(self, iterable=None, tee_data=None):
- if tee_data:
- self.tee_data = tee_data
- self.pos = 0
- # <=> Copy constructor
- elif isinstance(iterable, TeeObject):
- self.tee_data = iterable.tee_data
- self.pos = iterable.pos
- else:
- self.tee_data = TeeData(iter(iterable))
- self.pos = 0
-
- def next(self):
- data = self.tee_data[self.pos]
- self.pos += 1
- return data
-
- def __iter__(self):
- return self
-
-
- at builtinify
-def tee(iterable, n=2):
- """Return n independent iterators from a single iterable.
- Note : once tee() has made a split, the original iterable
- should not be used anywhere else; otherwise, the iterable could get
- advanced without the tee objects being informed.
-
- Note : this member of the toolkit may require significant auxiliary
- storage (depending on how much temporary data needs to be stored).
- In general, if one iterator is going to use most or all of the
- data before the other iterator, it is faster to use list() instead
- of tee()
-
- Equivalent to :
-
- def tee(iterable, n=2):
- def gen(next, data={}, cnt=[0]):
- for i in count():
- if i == cnt[0]:
- item = data[i] = next()
- cnt[0] += 1
- else:
- item = data.pop(i)
- yield item
- it = iter(iterable)
- return tuple([gen(it.next) for i in range(n)])
- """
- if isinstance(iterable, TeeObject):
- # a,b = tee(range(10)) ; c,d = tee(a) ; self.assert_(a is c)
- return tuple([iterable] +
- [TeeObject(tee_data=iterable.tee_data) for i in xrange(n-1)])
- tee_data = TeeData(iter(iterable))
- return tuple([TeeObject(tee_data=tee_data) for i in xrange(n)])
+try:
+ from __builtin_itertools import *
+ from __builtin_itertools import __doc__
+except ImportError:
+ from _itertools import *
+ from _itertools import __doc__
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -15,7 +15,7 @@
* `FAQ`_: some frequently asked questions.
-* `Release 1.6`_: the latest official release
+* `Release 1.7`_: the latest official release
* `PyPy Blog`_: news and status info about PyPy
@@ -75,7 +75,7 @@
.. _`Getting Started`: getting-started.html
.. _`Papers`: extradoc.html
.. _`Videos`: video-index.html
-.. _`Release 1.6`: http://pypy.org/download.html
+.. _`Release 1.7`: http://pypy.org/download.html
.. _`speed.pypy.org`: http://speed.pypy.org
.. _`RPython toolchain`: translation.html
.. _`potential project ideas`: project-ideas.html
@@ -120,9 +120,9 @@
Windows, on top of .NET, and on top of Java.
To dig into PyPy it is recommended to try out the current
Mercurial default branch, which is always working or mostly working,
-instead of the latest release, which is `1.6`__.
+instead of the latest release, which is `1.7`__.
-.. __: release-1.6.0.html
+.. __: release-1.7.0.html
PyPy is mainly developed on Linux and Mac OS X. Windows is supported,
but platform-specific bugs tend to take longer before we notice and fix
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -20,7 +20,7 @@
from pypy.jit.backend.llgraph import symbolic
from pypy.jit.codewriter import longlong
-from pypy.rlib import libffi
+from pypy.rlib import libffi, clibffi
from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
from pypy.rlib.rarithmetic import ovfcheck
from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
@@ -1432,6 +1432,10 @@
res = _getinteriorfield_raw(libffi.types.slong, array, index, width, ofs)
return res
+def do_getinteriorfield_raw_float(array, index, width, ofs):
+ res = _getinteriorfield_raw(libffi.types.double, array, index, width, ofs)
+ return res
+
def _getfield_raw(struct, fieldnum):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
@@ -1510,12 +1514,17 @@
do_setinteriorfield_gc_float = new_setinteriorfield_gc(cast_from_floatstorage)
do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)
-def new_setinteriorfield_raw(ffitype):
+def new_setinteriorfield_raw(cast_func, ffitype):
def do_setinteriorfield_raw(array, index, newvalue, width, ofs):
addr = rffi.cast(rffi.VOIDP, array)
+ for TYPE, ffitype2 in clibffi.ffitype_map:
+ if ffitype2 is ffitype:
+ newvalue = cast_func(TYPE, newvalue)
+ break
return libffi.array_setitem(ffitype, width, addr, index, ofs, newvalue)
return do_setinteriorfield_raw
-do_setinteriorfield_raw_int = new_setinteriorfield_raw(libffi.types.slong)
+do_setinteriorfield_raw_int = new_setinteriorfield_raw(cast_from_int, libffi.types.slong)
+do_setinteriorfield_raw_float = new_setinteriorfield_raw(cast_from_floatstorage, libffi.types.double)
def do_setfield_raw_int(struct, fieldnum, newvalue):
STRUCT, fieldname = symbolic.TokenToField[fieldnum]
diff --git a/pypy/jit/backend/llsupport/test/test_regalloc.py b/pypy/jit/backend/llsupport/test/test_regalloc.py
--- a/pypy/jit/backend/llsupport/test/test_regalloc.py
+++ b/pypy/jit/backend/llsupport/test/test_regalloc.py
@@ -2,6 +2,8 @@
from pypy.jit.metainterp.history import BoxInt, ConstInt, BoxFloat, INT, FLOAT
from pypy.jit.backend.llsupport.regalloc import FrameManager
from pypy.jit.backend.llsupport.regalloc import RegisterManager as BaseRegMan
+from pypy.jit.tool.oparser import parse
+from pypy.jit.backend.detect_cpu import getcpuclass
def newboxes(*values):
return [BoxInt(v) for v in values]
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -167,26 +167,22 @@
operations = cpu.gc_ll_descr.rewrite_assembler(cpu, operations,
allgcrefs)
# compute longevity of variables
- longevity = self._compute_vars_longevity(inputargs, operations)
+ longevity, useful = self._compute_vars_longevity(inputargs, operations)
self.longevity = longevity
self.rm = gpr_reg_mgr_cls(longevity,
frame_manager = self.fm,
assembler = self.assembler)
self.xrm = xmm_reg_mgr_cls(longevity, frame_manager = self.fm,
assembler = self.assembler)
- return operations
+ return operations, useful
def prepare_loop(self, inputargs, operations, looptoken, allgcrefs):
- operations = self._prepare(inputargs, operations, allgcrefs)
- jump = operations[-1]
- loop_consts = self._compute_loop_consts(inputargs, jump, looptoken)
- self.loop_consts = loop_consts
- return self._process_inputargs(inputargs), operations
+ operations, useful = self._prepare(inputargs, operations, allgcrefs)
+ return self._process_inputargs(inputargs, useful), operations
def prepare_bridge(self, prev_depths, inputargs, arglocs, operations,
allgcrefs):
- operations = self._prepare(inputargs, operations, allgcrefs)
- self.loop_consts = {}
+ operations, _ = self._prepare(inputargs, operations, allgcrefs)
self._update_bindings(arglocs, inputargs)
self.fm.frame_depth = prev_depths[0]
self.param_depth = prev_depths[1]
@@ -195,7 +191,7 @@
def reserve_param(self, n):
self.param_depth = max(self.param_depth, n)
- def _process_inputargs(self, inputargs):
+ def _process_inputargs(self, inputargs, useful):
# XXX we can sort out here by longevity if we need something
# more optimal
floatlocs = [None] * len(inputargs)
@@ -211,7 +207,7 @@
arg = inputargs[i]
assert not isinstance(arg, Const)
reg = None
- if arg not in self.loop_consts and self.longevity[arg][1] > -1:
+ if self.longevity[arg][1] > -1 and arg in useful:
if arg.type == FLOAT:
# xxx is it really a good idea? at the first CALL they
# will all be flushed anyway
@@ -287,15 +283,15 @@
else:
return self.xrm.make_sure_var_in_reg(var, forbidden_vars)
- def _compute_loop_consts(self, inputargs, jump, looptoken):
- if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
- loop_consts = {}
- else:
- loop_consts = {}
- for i in range(len(inputargs)):
- if inputargs[i] is jump.getarg(i):
- loop_consts[inputargs[i]] = i
- return loop_consts
+ #def _compute_loop_consts(self, inputargs, jump, looptoken):
+ # if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
+ # loop_consts = {}
+ # else:
+ # loop_consts = {}
+ # for i in range(len(inputargs)):
+ # if inputargs[i] is jump.getarg(i):
+ # loop_consts[inputargs[i]] = i
+ # return loop_consts
def _update_bindings(self, locs, inputargs):
# XXX this should probably go to llsupport/regalloc.py
@@ -450,8 +446,14 @@
def _compute_vars_longevity(self, inputargs, operations):
# compute a dictionary that maps variables to index in
# operations that is a "last-time-seen"
+
+ # returns a pair longevity/useful. Non-useful variables are ones that
+ # never appear in the assembler or it does not matter if they appear on
+ # stack or in registers. Main example is loop arguments that go
+ # only to guard operations or to jump or to finish
produced = {}
last_used = {}
+ useful = {}
for i in range(len(operations)-1, -1, -1):
op = operations[i]
if op.result:
@@ -459,8 +461,11 @@
continue
assert op.result not in produced
produced[op.result] = i
+ opnum = op.getopnum()
for j in range(op.numargs()):
arg = op.getarg(j)
+ if opnum != rop.JUMP and opnum != rop.FINISH:
+ useful[arg] = None
if isinstance(arg, Box) and arg not in last_used:
last_used[arg] = i
if op.is_guard():
@@ -486,7 +491,7 @@
longevity[arg] = (0, last_used[arg])
del last_used[arg]
assert len(last_used) == 0
- return longevity
+ return longevity, useful
def loc(self, v):
if v is None: # xxx kludgy
diff --git a/pypy/jit/backend/x86/test/test_regalloc.py b/pypy/jit/backend/x86/test/test_regalloc.py
--- a/pypy/jit/backend/x86/test/test_regalloc.py
+++ b/pypy/jit/backend/x86/test/test_regalloc.py
@@ -149,6 +149,13 @@
self.cpu.execute_token(loop.token)
return loop
+ def prepare_loop(self, ops):
+ loop = self.parse(ops)
+ regalloc = RegAlloc(self.cpu.assembler, False)
+ regalloc.prepare_loop(loop.inputargs, loop.operations,
+ loop.token, [])
+ return regalloc
+
def getint(self, index):
return self.cpu.get_latest_value_int(index)
@@ -422,6 +429,35 @@
self.run(loop)
assert self.getints(9) == range(9)
+ def test_loopargs(self):
+ ops = """
+ [i0, i1, i2, i3]
+ i4 = int_add(i0, i1)
+ jump(i4, i1, i2, i3)
+ """
+ regalloc = self.prepare_loop(ops)
+ assert len(regalloc.rm.reg_bindings) == 2
+
+ def test_loopargs_2(self):
+ ops = """
+ [i0, i1, i2, i3]
+ i4 = int_add(i0, i1)
+ finish(i4, i1, i2, i3)
+ """
+ regalloc = self.prepare_loop(ops)
+ assert len(regalloc.rm.reg_bindings) == 2
+
+ def test_loopargs_3(self):
+ ops = """
+ [i0, i1, i2, i3]
+ i4 = int_add(i0, i1)
+ guard_true(i4) [i0, i1, i2, i3, i4]
+ jump(i4, i1, i2, i3)
+ """
+ regalloc = self.prepare_loop(ops)
+ assert len(regalloc.rm.reg_bindings) == 2
+
+
class TestRegallocCompOps(BaseTestRegalloc):
def test_cmp_op_0(self):
diff --git a/pypy/jit/backend/x86/test/test_zrpy_gc.py b/pypy/jit/backend/x86/test/test_zrpy_gc.py
--- a/pypy/jit/backend/x86/test/test_zrpy_gc.py
+++ b/pypy/jit/backend/x86/test/test_zrpy_gc.py
@@ -457,6 +457,46 @@
def test_compile_framework_7(self):
self.run('compile_framework_7')
+ def define_compile_framework_7_interior(cls):
+ # Array of structs containing pointers (test the write barrier
+ # for setinteriorfield_gc)
+ S = lltype.GcStruct('S', ('i', lltype.Signed))
+ A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)),
+ ('y', lltype.Ptr(S)),
+ ('z', lltype.Ptr(S))))
+ class Glob:
+ a = lltype.nullptr(A)
+ glob = Glob()
+ #
+ def make_s(i):
+ s = lltype.malloc(S)
+ s.i = i
+ return s
+ #
+ @unroll_safe
+ def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+ a = glob.a
+ if not a:
+ a = glob.a = lltype.malloc(A, 10)
+ i = 0
+ while i < 10:
+ a[i].x = make_s(n + i * 100 + 1)
+ a[i].y = make_s(n + i * 100 + 2)
+ a[i].z = make_s(n + i * 100 + 3)
+ i += 1
+ i = 0
+ while i < 10:
+ check(a[i].x.i == n + i * 100 + 1)
+ check(a[i].y.i == n + i * 100 + 2)
+ check(a[i].z.i == n + i * 100 + 3)
+ i += 1
+ return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+ f(123, *[None]*11) # check that the check() are ok
+ return None, f, None
+
+ def test_compile_framework_7_interior(self):
+ self.run('compile_framework_7_interior')
+
def define_compile_framework_8(cls):
# Array of pointers, of unknown length (test write_barrier_from_array)
def before(n, x):
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -247,7 +247,7 @@
if funcobj.random_effects_on_gcobjs:
return True
except (AttributeError, lltype.DelayedPointer):
- pass
+ return True # better safe than sorry
return super(RandomEffectsAnalyzer, self).analyze_external_call(
op, seen)
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -210,6 +210,8 @@
def rewrite_op_cast_pointer(self, op):
newop = self.rewrite_op_same_as(op)
assert newop is None
+ return
+ # disabled for now
if (self._is_rclass_instance(op.args[0]) and
self._is_rclass_instance(op.result)):
FROM = op.args[0].concretetype.TO
@@ -220,6 +222,9 @@
return [None, # hack, do the right renaming from op.args[0] to op.result
SpaceOperation("record_known_class", [op.args[0], const_vtable], None)]
+ def rewrite_op_jit_record_known_class(self, op):
+ return SpaceOperation("record_known_class", [op.args[0], op.args[1]], None)
+
def rewrite_op_cast_bool_to_int(self, op): pass
def rewrite_op_cast_bool_to_uint(self, op): pass
def rewrite_op_cast_char_to_int(self, op): pass
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -14,7 +14,7 @@
from pypy.rlib.jit import (JitDriver, we_are_jitted, hint, dont_look_inside,
loop_invariant, elidable, promote, jit_debug, assert_green,
AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff,
- isconstant, isvirtual, promote_string, set_param)
+ isconstant, isvirtual, promote_string, set_param, record_known_class)
from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rpython.ootypesystem import ootype
@@ -3585,7 +3585,8 @@
self.interp_operations(f, [5], translationoptions=translationoptions)
- def test_annotation_gives_knowledge_to_tracer(self):
+ def test_annotation_gives_class_knowledge_to_tracer(self):
+ py.test.skip("disabled")
class Base(object):
pass
class A(Base):
@@ -3645,6 +3646,70 @@
# here it works again
self.check_operations_history(guard_class=0, record_known_class=1)
+ def test_give_class_knowledge_to_tracer_explicitly(self):
+ from pypy.rpython.lltypesystem.lloperation import llop
+ class Base(object):
+ def f(self):
+ raise NotImplementedError
+ def g(self):
+ raise NotImplementedError
+ class A(Base):
+ def f(self):
+ return self.a
+ def g(self):
+ return self.a + 1
+ class B(Base):
+ def f(self):
+ return self.b
+ def g(self):
+ return self.b + 1
+ class C(B):
+ def f(self):
+ self.c += 1
+ return self.c
+ def g(self):
+ return self.c + 1
+ @dont_look_inside
+ def make(x):
+ if x > 0:
+ a = A()
+ a.a = x + 1
+ elif x < 0:
+ a = B()
+ a.b = -x
+ else:
+ a = C()
+ a.c = 10
+ return a
+ def f(x):
+ a = make(x)
+ if x > 0:
+ record_known_class(a, A)
+ z = a.f()
+ elif x < 0:
+ record_known_class(a, B)
+ z = a.f()
+ else:
+ record_known_class(a, C)
+ z = a.f()
+ return z + a.g()
+ res1 = f(6)
+ res2 = self.interp_operations(f, [6])
+ assert res1 == res2
+ self.check_operations_history(guard_class=0, record_known_class=1)
+
+ res1 = f(-6)
+ res2 = self.interp_operations(f, [-6])
+ assert res1 == res2
+ # cannot use record_known_class here, because B has a subclass
+ self.check_operations_history(guard_class=1)
+
+ res1 = f(0)
+ res2 = self.interp_operations(f, [0])
+ assert res1 == res2
+ # here it works again
+ self.check_operations_history(guard_class=0, record_known_class=1)
+
class TestLLtype(BaseLLtypeTests, LLJitMixin):
def test_tagged(self):
diff --git a/pypy/module/itertools/__init__.py b/pypy/module/itertools/__init__.py
--- a/pypy/module/itertools/__init__.py
+++ b/pypy/module/itertools/__init__.py
@@ -23,6 +23,7 @@
dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails
groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)
"""
+ applevel_name = '__builtin_itertools'
interpleveldefs = {
'chain' : 'interp_itertools.W_Chain',
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
@@ -5,10 +5,11 @@
applevel_name = 'numpypy'
interpleveldefs = {
- 'array': 'interp_numarray.NDimArray',
+ 'ndarray': 'interp_numarray.W_NDimArray',
'dtype': 'interp_dtype.W_Dtype',
'ufunc': 'interp_ufuncs.W_Ufunc',
+ 'array': 'interp_numarray.array',
'zeros': 'interp_numarray.zeros',
'empty': 'interp_numarray.zeros',
'ones': 'interp_numarray.ones',
@@ -16,8 +17,22 @@
'fromstring': 'interp_support.fromstring',
'flatiter': 'interp_numarray.W_FlatIterator',
- 'True_': 'space.w_True',
- 'False_': 'space.w_False',
+ 'True_': 'types.Bool.True',
+ 'False_': 'types.Bool.False',
+
+ 'generic': 'interp_boxes.W_GenericBox',
+ 'number': 'interp_boxes.W_NumberBox',
+ 'integer': 'interp_boxes.W_IntegerBox',
+ 'signedinteger': 'interp_boxes.W_SignedIntegerBox',
+ 'bool_': 'interp_boxes.W_BoolBox',
+ 'int8': 'interp_boxes.W_Int8Box',
+ 'int16': 'interp_boxes.W_Int16Box',
+ 'int32': 'interp_boxes.W_Int32Box',
+ 'int64': 'interp_boxes.W_Int64Box',
+ 'int_': 'interp_boxes.W_LongBox',
+ 'inexact': 'interp_boxes.W_InexactBox',
+ 'floating': 'interp_boxes.W_FloatingBox',
+ 'float64': 'interp_boxes.W_Float64Box',
}
# ufuncs
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -3,13 +3,16 @@
It should not be imported by the module itself
"""
+import re
+
from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
-from pypy.module.micronumpy.interp_dtype import W_Float64Dtype, W_BoolDtype
+from pypy.module.micronumpy import interp_boxes
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
from pypy.module.micronumpy.interp_numarray import (Scalar, BaseArray,
- descr_new_array, scalar_w, NDimArray)
+ scalar_w, W_NDimArray, array)
from pypy.module.micronumpy import interp_ufuncs
-from pypy.rlib.objectmodel import specialize
-import re
+from pypy.rlib.objectmodel import specialize, instantiate
+
class BogusBytecode(Exception):
pass
@@ -48,15 +51,12 @@
def __init__(self):
"""NOT_RPYTHON"""
self.fromcache = InternalSpaceCache(self).getorbuild
- self.w_float64dtype = W_Float64Dtype(self)
def issequence_w(self, w_obj):
- return isinstance(w_obj, ListObject) or isinstance(w_obj, NDimArray)
+ return isinstance(w_obj, ListObject) or isinstance(w_obj, W_NDimArray)
def isinstance_w(self, w_obj, w_tp):
- if w_obj.tp == w_tp:
- return True
- return False
+ return w_obj.tp == w_tp
def decode_index4(self, w_idx, size):
if isinstance(w_idx, IntObject):
@@ -97,8 +97,10 @@
fixedview = listview
def float(self, w_obj):
- assert isinstance(w_obj, FloatObject)
- return w_obj
+ if isinstance(w_obj, FloatObject):
+ return w_obj
+ assert isinstance(w_obj, interp_boxes.W_GenericBox)
+ return self.float(w_obj.descr_float(self))
def float_w(self, w_obj):
assert isinstance(w_obj, FloatObject)
@@ -112,7 +114,10 @@
raise NotImplementedError
def int(self, w_obj):
- return w_obj
+ if isinstance(w_obj, IntObject):
+ return w_obj
+ assert isinstance(w_obj, interp_boxes.W_GenericBox)
+ return self.int(w_obj.descr_int(self))
def is_true(self, w_obj):
assert isinstance(w_obj, BoolObject)
@@ -135,6 +140,9 @@
assert isinstance(what, tp)
return what
+ def allocate_instance(self, klass, w_subtype):
+ return instantiate(klass)
+
def len_w(self, w_obj):
if isinstance(w_obj, ListObject):
return len(w_obj.items)
@@ -247,7 +255,7 @@
w_rhs = self.rhs.execute(interp)
if not isinstance(w_lhs, BaseArray):
# scalar
- dtype = interp.space.fromcache(W_Float64Dtype)
+ dtype = get_dtype_cache(interp.space).w_float64dtype
w_lhs = scalar_w(interp.space, dtype, w_lhs)
assert isinstance(w_lhs, BaseArray)
if self.name == '+':
@@ -264,8 +272,9 @@
w_res = w_lhs.descr_getitem(interp.space, w_rhs)
else:
raise NotImplementedError
- if not isinstance(w_res, BaseArray):
- dtype = interp.space.fromcache(W_Float64Dtype)
+ if (not isinstance(w_res, BaseArray) and
+ not isinstance(w_res, interp_boxes.W_GenericBox)):
+ dtype = get_dtype_cache(interp.space).w_float64dtype
w_res = scalar_w(interp.space, dtype, w_res)
return w_res
@@ -283,7 +292,7 @@
return space.wrap(self.v)
def execute(self, interp):
- return FloatObject(self.v)
+ return interp.space.wrap(self.v)
class RangeConstant(Node):
def __init__(self, v):
@@ -291,10 +300,10 @@
def execute(self, interp):
w_list = interp.space.newlist(
- [interp.space.wrap(float(i)) for i in range(self.v)])
- dtype = interp.space.fromcache(W_Float64Dtype)
- return descr_new_array(interp.space, None, w_list, w_dtype=dtype,
- w_order=None)
+ [interp.space.wrap(float(i)) for i in range(self.v)]
+ )
+ dtype = get_dtype_cache(interp.space).w_float64dtype
+ return array(interp.space, w_list, w_dtype=dtype, w_order=None)
def __repr__(self):
return 'Range(%s)' % self.v
@@ -315,9 +324,8 @@
def execute(self, interp):
w_list = self.wrap(interp.space)
- dtype = interp.space.fromcache(W_Float64Dtype)
- return descr_new_array(interp.space, None, w_list, w_dtype=dtype,
- w_order=None)
+ dtype = get_dtype_cache(interp.space).w_float64dtype
+ return array(interp.space, w_list, w_dtype=dtype, w_order=None)
def __repr__(self):
return "[" + ", ".join([repr(item) for item in self.items]) + "]"
@@ -384,9 +392,11 @@
if isinstance(w_res, BaseArray):
return w_res
if isinstance(w_res, FloatObject):
- dtype = interp.space.fromcache(W_Float64Dtype)
+ dtype = get_dtype_cache(interp.space).w_float64dtype
elif isinstance(w_res, BoolObject):
- dtype = interp.space.fromcache(W_BoolDtype)
+ dtype = get_dtype_cache(interp.space).w_booldtype
+ elif isinstance(w_res, interp_boxes.W_GenericBox):
+ dtype = w_res.get_dtype(interp.space)
else:
dtype = None
return scalar_w(interp.space, dtype, w_res)
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -0,0 +1,267 @@
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
+from pypy.objspace.std.floattype import float_typedef
+from pypy.objspace.std.inttype import int_typedef
+from pypy.objspace.std.typeobject import W_TypeObject
+from pypy.rlib.rarithmetic import LONG_BIT
+from pypy.tool.sourcetools import func_with_new_name
+
+
+MIXIN_64 = (int_typedef,) if LONG_BIT == 64 else ()
+
+def new_dtype_getter(name):
+ def get_dtype(space):
+ from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+ return getattr(get_dtype_cache(space), "w_%sdtype" % name)
+ def new(space, w_subtype, w_value):
+ dtype = get_dtype(space)
+ return dtype.itemtype.coerce_subtype(space, w_subtype, w_value)
+ return func_with_new_name(new, name + "_box_new"), staticmethod(get_dtype)
+
+class PrimitiveBox(object):
+ _mixin_ = True
+
+ def __init__(self, value):
+ self.value = value
+
+ def convert_to(self, dtype):
+ return dtype.box(self.value)
+
+class W_GenericBox(Wrappable):
+ _attrs_ = ()
+
+ def descr__new__(space, w_subtype, __args__):
+ assert isinstance(w_subtype, W_TypeObject)
+ raise operationerrfmt(space.w_TypeError, "cannot create '%s' instances",
+ w_subtype.get_module_type_name()
+ )
+
+ def descr_str(self, space):
+ return self.descr_repr(space)
+
+ def descr_repr(self, space):
+ return space.wrap(self.get_dtype(space).itemtype.str_format(self))
+
+ def descr_int(self, space):
+ box = self.convert_to(W_LongBox.get_dtype(space))
+ assert isinstance(box, W_LongBox)
+ return space.wrap(box.value)
+
+ def descr_float(self, space):
+ box = self.convert_to(W_Float64Box.get_dtype(space))
+ assert isinstance(box, W_Float64Box)
+ return space.wrap(box.value)
+
+ def descr_nonzero(self, space):
+ dtype = self.get_dtype(space)
+ return space.wrap(dtype.itemtype.bool(self))
+
+ def _binop_impl(ufunc_name):
+ def impl(self, space, w_other):
+ from pypy.module.micronumpy import interp_ufuncs
+ return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other])
+ return func_with_new_name(impl, "binop_%s_impl" % ufunc_name)
+
+ def _binop_right_impl(ufunc_name):
+ def impl(self, space, w_other):
+ from pypy.module.micronumpy import interp_ufuncs
+ return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self])
+ return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name)
+
+ def _unaryop_impl(ufunc_name):
+ def impl(self, space):
+ from pypy.module.micronumpy import interp_ufuncs
+ return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
+ return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name)
+
+ descr_add = _binop_impl("add")
+ descr_sub = _binop_impl("subtract")
+ descr_mul = _binop_impl("multiply")
+ descr_div = _binop_impl("divide")
+ descr_eq = _binop_impl("equal")
+ descr_ne = _binop_impl("not_equal")
+ descr_lt = _binop_impl("less")
+ descr_le = _binop_impl("less_equal")
+ descr_gt = _binop_impl("greater")
+ descr_ge = _binop_impl("greater_equal")
+
+ descr_radd = _binop_right_impl("add")
+ descr_rmul = _binop_right_impl("multiply")
+
+ descr_neg = _unaryop_impl("negative")
+ descr_abs = _unaryop_impl("absolute")
+
+
+class W_BoolBox(W_GenericBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("bool")
+
+class W_NumberBox(W_GenericBox):
+ _attrs_ = ()
+
+class W_IntegerBox(W_NumberBox):
+ pass
+
+class W_SignedIntegerBox(W_IntegerBox):
+ pass
+
+class W_UnsignedIntgerBox(W_IntegerBox):
+ pass
+
+class W_Int8Box(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("int8")
+
+class W_UInt8Box(W_UnsignedIntgerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("uint8")
+
+class W_Int16Box(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("int16")
+
+class W_UInt16Box(W_UnsignedIntgerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("uint16")
+
+class W_Int32Box(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("int32")
+
+class W_UInt32Box(W_UnsignedIntgerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("uint32")
+
+class W_LongBox(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("long")
+
+class W_ULongBox(W_UnsignedIntgerBox, PrimitiveBox):
+ pass
+
+class W_Int64Box(W_SignedIntegerBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("int64")
+
+class W_UInt64Box(W_UnsignedIntgerBox, PrimitiveBox):
+ pass
+
+class W_InexactBox(W_NumberBox):
+ _attrs_ = ()
+
+class W_FloatingBox(W_InexactBox):
+ _attrs_ = ()
+
+class W_Float32Box(W_FloatingBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("float32")
+
+class W_Float64Box(W_FloatingBox, PrimitiveBox):
+ descr__new__, get_dtype = new_dtype_getter("float64")
+
+
+
+W_GenericBox.typedef = TypeDef("generic",
+ __module__ = "numpypy",
+
+ __new__ = interp2app(W_GenericBox.descr__new__.im_func),
+
+ __str__ = interp2app(W_GenericBox.descr_str),
+ __repr__ = interp2app(W_GenericBox.descr_repr),
+ __int__ = interp2app(W_GenericBox.descr_int),
+ __float__ = interp2app(W_GenericBox.descr_float),
+ __nonzero__ = interp2app(W_GenericBox.descr_nonzero),
+
+ __add__ = interp2app(W_GenericBox.descr_add),
+ __sub__ = interp2app(W_GenericBox.descr_sub),
+ __mul__ = interp2app(W_GenericBox.descr_mul),
+ __div__ = interp2app(W_GenericBox.descr_div),
+
+ __radd__ = interp2app(W_GenericBox.descr_add),
+ __rmul__ = interp2app(W_GenericBox.descr_rmul),
+
+ __eq__ = interp2app(W_GenericBox.descr_eq),
+ __ne__ = interp2app(W_GenericBox.descr_ne),
+ __lt__ = interp2app(W_GenericBox.descr_lt),
+ __le__ = interp2app(W_GenericBox.descr_le),
+ __gt__ = interp2app(W_GenericBox.descr_gt),
+ __ge__ = interp2app(W_GenericBox.descr_ge),
+
+ __neg__ = interp2app(W_GenericBox.descr_neg),
+ __abs__ = interp2app(W_GenericBox.descr_abs),
+)
+
+W_BoolBox.typedef = TypeDef("bool_", W_GenericBox.typedef,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_BoolBox.descr__new__.im_func),
+)
+
+W_NumberBox.typedef = TypeDef("number", W_GenericBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_IntegerBox.typedef = TypeDef("integer", W_NumberBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_SignedIntegerBox.typedef = TypeDef("signedinteger", W_IntegerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Int8Box.typedef = TypeDef("int8", W_SignedIntegerBox.typedef,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Int8Box.descr__new__.im_func),
+)
+
+W_UInt8Box.typedef = TypeDef("uint8", W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Int16Box.typedef = TypeDef("int16", W_SignedIntegerBox.typedef,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Int16Box.descr__new__.im_func),
+)
+
+W_UInt16Box.typedef = TypeDef("uint16", W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Int32Box.typedef = TypeDef("int32", W_SignedIntegerBox.typedef,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Int32Box.descr__new__.im_func),
+)
+
+W_UInt32Box.typedef = TypeDef("uint32", W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+if LONG_BIT == 32:
+ long_name = "int32"
+elif LONG_BIT == 64:
+ long_name = "int64"
+W_LongBox.typedef = TypeDef(long_name, (W_SignedIntegerBox.typedef, int_typedef,),
+ __module__ = "numpypy",
+)
+
+W_ULongBox.typedef = TypeDef("u" + long_name, W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Int64Box.typedef = TypeDef("int64", (W_SignedIntegerBox.typedef,) + MIXIN_64,
+ __module__ = "numpypy",
+ __new__ = interp2app(W_Int64Box.descr__new__.im_func),
+)
+
+W_UInt64Box.typedef = TypeDef("uint64", W_UnsignedIntgerBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_InexactBox.typedef = TypeDef("inexact", W_NumberBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_FloatingBox.typedef = TypeDef("floating", W_InexactBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Float32Box.typedef = TypeDef("float32", W_FloatingBox.typedef,
+ __module__ = "numpypy",
+)
+
+W_Float64Box.typedef = TypeDef("float64", (W_FloatingBox.typedef, float_typedef),
+ __module__ = "numpypy",
+
+ __new__ = interp2app(W_Float64Box.descr__new__.im_func),
+)
\ 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
@@ -1,16 +1,11 @@
-import functools
-import math
-
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty
-from pypy.module.micronumpy import signature
-from pypy.objspace.std.floatobject import float2string
-from pypy.rlib import rarithmetic, rfloat
-from pypy.rlib.rarithmetic import LONG_BIT, widen
-from pypy.rlib.objectmodel import specialize, enforceargs
-from pypy.rlib.unroll import unrolling_iterable
+from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
+ interp_attrproperty, interp_attrproperty_w)
+from pypy.module.micronumpy import types, signature, interp_boxes
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import LONG_BIT
from pypy.rpython.lltypesystem import lltype, rffi
@@ -19,523 +14,218 @@
BOOLLTR = "b"
FLOATINGLTR = "f"
+
+VOID_STORAGE = lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True})
+
class W_Dtype(Wrappable):
- def __init__(self, space):
- pass
+ _immuable_fields_ = ["itemtype", "num", "kind"]
+
+ def __init__(self, itemtype, num, kind, name, char, w_box_type, alternate_constructors=[]):
+ self.signature = signature.BaseSignature()
+ self.itemtype = itemtype
+ self.num = num
+ self.kind = kind
+ self.name = name
+ self.char = char
+ self.w_box_type = w_box_type
+ self.alternate_constructors = alternate_constructors
+
+ def malloc(self, length):
+ # XXX find out why test_zjit explodes with tracking of allocations
+ return lltype.malloc(VOID_STORAGE, self.itemtype.get_element_size() * length,
+ zero=True, flavor="raw",
+ track_allocation=False, add_memory_pressure=True
+ )
+
+ @specialize.argtype(1)
+ def box(self, value):
+ return self.itemtype.box(value)
+
+ def coerce(self, space, w_item):
+ return self.itemtype.coerce(space, w_item)
+
+ def getitem(self, storage, i):
+ return self.itemtype.read(storage, self.itemtype.get_element_size(), i, 0)
+
+ def setitem(self, storage, i, box):
+ self.itemtype.store(storage, self.itemtype.get_element_size(), i, 0, box)
+
+ def fill(self, storage, box, start, stop):
+ self.itemtype.fill(storage, self.itemtype.get_element_size(), box, start, stop, 0)
def descr__new__(space, w_subtype, w_dtype):
+ cache = get_dtype_cache(space)
+
if space.is_w(w_dtype, space.w_None):
- return space.fromcache(W_Float64Dtype)
+ return cache.w_float64dtype
+ elif space.isinstance_w(w_dtype, w_subtype):
+ return w_dtype
elif space.isinstance_w(w_dtype, space.w_str):
- dtype = space.str_w(w_dtype)
- for alias, dtype_class in dtypes_by_alias:
- if alias == dtype:
- return space.fromcache(dtype_class)
- elif isinstance(space.interpclass_w(w_dtype), W_Dtype):
- return w_dtype
- elif space.isinstance_w(w_dtype, space.w_type):
- for typename, dtype_class in dtypes_by_apptype:
- if space.is_w(getattr(space, "w_%s" % typename), w_dtype):
- return space.fromcache(dtype_class)
+ name = space.str_w(w_dtype)
+ for dtype in cache.builtin_dtypes:
+ if dtype.name == name or dtype.char == name:
+ return dtype
+ else:
+ for dtype in cache.builtin_dtypes:
+ if w_dtype in dtype.alternate_constructors:
+ return dtype
+ if w_dtype is dtype.w_box_type:
+ return dtype
raise OperationError(space.w_TypeError, space.wrap("data type not understood"))
+ def descr_str(self, space):
+ return space.wrap(self.name)
+
def descr_repr(self, space):
return space.wrap("dtype('%s')" % self.name)
- def descr_str(self, space):
- return space.wrap(self.name)
+ def descr_get_itemsize(self, space):
+ return space.wrap(self.itemtype.get_element_size())
def descr_get_shape(self, space):
return space.newtuple([])
-
-class BaseBox(object):
- pass
-
-VOID_TP = lltype.Ptr(lltype.Array(lltype.Void, hints={'nolength': True, "uncast_on_llgraph": True}))
-
-def create_low_level_dtype(num, kind, name, aliases, applevel_types, T, valtype,
- expected_size=None):
-
- class Box(BaseBox):
- def __init__(self, val):
- self.val = val
-
- def wrap(self, space):
- val = self.val
- if valtype is rarithmetic.r_singlefloat:
- val = float(val)
- return space.wrap(val)
-
- def convert_to(self, dtype):
- return dtype.adapt_val(self.val)
- Box.__name__ = "%sBox" % T._name
-
- TP = lltype.Ptr(lltype.Array(T, hints={'nolength': True}))
- class W_LowLevelDtype(W_Dtype):
- signature = signature.BaseSignature()
-
- def erase(self, storage):
- return rffi.cast(VOID_TP, storage)
-
- def unerase(self, storage):
- return rffi.cast(TP, storage)
-
- @enforceargs(None, valtype)
- def box(self, value):
- return Box(value)
-
- def unbox(self, box):
- assert isinstance(box, Box)
- return box.val
-
- def unwrap(self, space, w_item):
- raise NotImplementedError
-
- def malloc(self, size):
- # XXX find out why test_zjit explodes with tracking of allocations
- return self.erase(lltype.malloc(TP.TO, size,
- zero=True, flavor="raw",
- track_allocation=False, add_memory_pressure=True
- ))
-
- def getitem(self, storage, i):
- return Box(self.unerase(storage)[i])
-
- def setitem(self, storage, i, item):
- self.unerase(storage)[i] = self.unbox(item)
-
- def setitem_w(self, space, storage, i, w_item):
- self.setitem(storage, i, self.unwrap(space, w_item))
-
- def fill(self, storage, item, start, stop):
- storage = self.unerase(storage)
- item = self.unbox(item)
- for i in xrange(start, stop):
- storage[i] = item
-
- @specialize.argtype(1)
- def adapt_val(self, val):
- return self.box(rffi.cast(TP.TO.OF, val))
-
- W_LowLevelDtype.__name__ = "W_%sDtype" % name.capitalize()
- W_LowLevelDtype.num = num
- W_LowLevelDtype.kind = kind
- W_LowLevelDtype.name = name
- W_LowLevelDtype.aliases = aliases
- W_LowLevelDtype.applevel_types = applevel_types
- W_LowLevelDtype.num_bytes = rffi.sizeof(T)
- if expected_size is not None:
- assert W_LowLevelDtype.num_bytes == expected_size
- return W_LowLevelDtype
-
-
-def binop(func):
- specialize.argtype(1, 2)(func)
- @functools.wraps(func)
- def impl(self, v1, v2):
- return self.adapt_val(func(self,
- self.for_computation(self.unbox(v1)),
- self.for_computation(self.unbox(v2)),
- ))
- return impl
-
-def raw_binop(func):
- specialize.argtype(1, 2)(func)
- # Returns the result unwrapped.
- @functools.wraps(func)
- def impl(self, v1, v2):
- return func(self,
- self.for_computation(self.unbox(v1)),
- self.for_computation(self.unbox(v2))
- )
- return impl
-
-def unaryop(func):
- specialize.argtype(1)(func)
- @functools.wraps(func)
- def impl(self, v):
- return self.adapt_val(func(self, self.for_computation(self.unbox(v))))
- return impl
-
-class ArithmeticTypeMixin(object):
- _mixin_ = True
-
- @binop
- def add(self, v1, v2):
- return v1 + v2
- @binop
- def sub(self, v1, v2):
- return v1 - v2
- @binop
- def mul(self, v1, v2):
- return v1 * v2
-
- @unaryop
- def pos(self, v):
- return +v
- @unaryop
- def neg(self, v):
- return -v
- @unaryop
- def abs(self, v):
- return abs(v)
-
- @binop
- def max(self, v1, v2):
- return max(v1, v2)
- @binop
- def min(self, v1, v2):
- return min(v1, v2)
-
- def bool(self, v):
- return bool(self.for_computation(self.unbox(v)))
- @raw_binop
- def eq(self, v1, v2):
- return v1 == v2
- @raw_binop
- def ne(self, v1, v2):
- return v1 != v2
- @raw_binop
- def lt(self, v1, v2):
- return v1 < v2
- @raw_binop
- def le(self, v1, v2):
- return v1 <= v2
- @raw_binop
- def gt(self, v1, v2):
- return v1 > v2
- @raw_binop
- def ge(self, v1, v2):
- return v1 >= v2
-
-
-class FloatArithmeticDtype(ArithmeticTypeMixin):
- _mixin_ = True
-
- def unwrap(self, space, w_item):
- return self.adapt_val(space.float_w(space.float(w_item)))
-
- def for_computation(self, v):
- return float(v)
-
- def str_format(self, item):
- return float2string(self.for_computation(self.unbox(item)), 'g', rfloat.DTSF_STR_PRECISION)
-
- @binop
- def div(self, v1, v2):
- # XXX this won't work after translation, probably requires ovfcheck
- try:
- return v1 / v2
- except ZeroDivisionError:
- if v1 == v2 == 0.0:
- return rfloat.NAN
- return rfloat.copysign(rfloat.INFINITY, v1 * v2)
- @binop
- def mod(self, v1, v2):
- return math.fmod(v1, v2)
- @binop
- def pow(self, v1, v2):
- return math.pow(v1, v2)
-
- @unaryop
- def sign(self, v):
- if v == 0.0:
- return 0.0
- return rfloat.copysign(1.0, v)
- @unaryop
- def reciprocal(self, v):
- if v == 0.0:
- return rfloat.copysign(rfloat.INFINITY, v)
- return 1.0 / v
- @unaryop
- def fabs(self, v):
- return math.fabs(v)
- @unaryop
- def floor(self, v):
- return math.floor(v)
-
- @binop
- def copysign(self, v1, v2):
- return math.copysign(v1, v2)
- @unaryop
- def exp(self, v):
- try:
- return math.exp(v)
- except OverflowError:
- return rfloat.INFINITY
- @unaryop
- def sin(self, v):
- return math.sin(v)
- @unaryop
- def cos(self, v):
- return math.cos(v)
- @unaryop
- def tan(self, v):
- return math.tan(v)
- @unaryop
- def arcsin(self, v):
- if not -1.0 <= v <= 1.0:
- return rfloat.NAN
- return math.asin(v)
- @unaryop
- def arccos(self, v):
- if not -1.0 <= v <= 1.0:
- return rfloat.NAN
- return math.acos(v)
- @unaryop
- def arctan(self, v):
- return math.atan(v)
- @unaryop
- def arcsinh(self, v):
- return math.asinh(v)
- @unaryop
- 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)
- @unaryop
- def sqrt(self, v):
- try:
- return math.sqrt(v)
- except ValueError:
- return rfloat.NAN
-
-class IntegerArithmeticDtype(ArithmeticTypeMixin):
- _mixin_ = True
-
- def unwrap(self, space, w_item):
- return self.adapt_val(space.int_w(space.int(w_item)))
-
- def for_computation(self, v):
- return widen(v)
-
- def str_format(self, item):
- return str(widen(self.unbox(item)))
-
- @binop
- def div(self, v1, v2):
- if v2 == 0:
- return 0
- return v1 / v2
- @binop
- def mod(self, v1, v2):
- return v1 % v2
- @binop
- def pow(self, v1, v2):
- res = 1
- while v2 > 0:
- if v2 & 1:
- res *= v1
- v2 >>= 1
- if v2 == 0:
- break
- v1 *= v1
- return res
-
-
-class SignedIntegerArithmeticDtype(IntegerArithmeticDtype):
- _mixin_ = True
-
- @unaryop
- def sign(self, v):
- if v > 0:
- return 1
- elif v < 0:
- return -1
- else:
- assert v == 0
- return 0
-
-class UnsignedIntegerArithmeticDtype(IntegerArithmeticDtype):
- _mixin_ = True
-
- @unaryop
- def sign(self, v):
- return int(v != 0)
-
-
-W_BoolDtype = create_low_level_dtype(
- num = 0, kind = BOOLLTR, name = "bool",
- aliases = ["?", "bool", "bool8"],
- applevel_types = ["bool"],
- T = lltype.Bool,
- valtype = bool,
-)
-class W_BoolDtype(SignedIntegerArithmeticDtype, W_BoolDtype):
- def unwrap(self, space, w_item):
- return self.adapt_val(space.is_true(w_item))
-
- def str_format(self, item):
- v = self.unbox(item)
- return "True" if v else "False"
-
- def for_computation(self, v):
- return int(v)
-
-W_Int8Dtype = create_low_level_dtype(
- num = 1, kind = SIGNEDLTR, name = "int8",
- aliases = ["b", "int8", "i1"],
- applevel_types = [],
- T = rffi.SIGNEDCHAR,
- valtype = rffi.SIGNEDCHAR._type,
- expected_size = 1,
-)
-class W_Int8Dtype(SignedIntegerArithmeticDtype, W_Int8Dtype):
- pass
-
-W_UInt8Dtype = create_low_level_dtype(
- num = 2, kind = UNSIGNEDLTR, name = "uint8",
- aliases = ["B", "uint8", "I1"],
- applevel_types = [],
- T = rffi.UCHAR,
- valtype = rffi.UCHAR._type,
- expected_size = 1,
-)
-class W_UInt8Dtype(UnsignedIntegerArithmeticDtype, W_UInt8Dtype):
- pass
-
-W_Int16Dtype = create_low_level_dtype(
- num = 3, kind = SIGNEDLTR, name = "int16",
- aliases = ["h", "int16", "i2"],
- applevel_types = [],
- T = rffi.SHORT,
- valtype = rffi.SHORT._type,
- expected_size = 2,
-)
-class W_Int16Dtype(SignedIntegerArithmeticDtype, W_Int16Dtype):
- pass
-
-W_UInt16Dtype = create_low_level_dtype(
- num = 4, kind = UNSIGNEDLTR, name = "uint16",
- aliases = ["H", "uint16", "I2"],
- applevel_types = [],
- T = rffi.USHORT,
- valtype = rffi.USHORT._type,
- expected_size = 2,
-)
-class W_UInt16Dtype(UnsignedIntegerArithmeticDtype, W_UInt16Dtype):
- pass
-
-W_Int32Dtype = create_low_level_dtype(
- num = 5, kind = SIGNEDLTR, name = "int32",
- aliases = ["i", "int32", "i4"],
- applevel_types = [],
- T = rffi.INT,
- valtype = rffi.INT._type,
- expected_size = 4,
-)
-class W_Int32Dtype(SignedIntegerArithmeticDtype, W_Int32Dtype):
- pass
-
-W_UInt32Dtype = create_low_level_dtype(
- num = 6, kind = UNSIGNEDLTR, name = "uint32",
- aliases = ["I", "uint32", "I4"],
- applevel_types = [],
- T = rffi.UINT,
- valtype = rffi.UINT._type,
- expected_size = 4,
-)
-class W_UInt32Dtype(UnsignedIntegerArithmeticDtype, W_UInt32Dtype):
- pass
-
-W_Int64Dtype = create_low_level_dtype(
- num = 9, kind = SIGNEDLTR, name = "int64",
- aliases = ["q", "int64", "i8"],
- applevel_types = ["long"],
- T = rffi.LONGLONG,
- valtype = rffi.LONGLONG._type,
- expected_size = 8,
-)
-class W_Int64Dtype(SignedIntegerArithmeticDtype, W_Int64Dtype):
- pass
-
-W_UInt64Dtype = create_low_level_dtype(
- num = 10, kind = UNSIGNEDLTR, name = "uint64",
- aliases = ["Q", "uint64", "I8"],
- applevel_types = [],
- T = rffi.ULONGLONG,
- valtype = rffi.ULONGLONG._type,
- expected_size = 8,
-)
-class W_UInt64Dtype(UnsignedIntegerArithmeticDtype, W_UInt64Dtype):
- pass
-
-if LONG_BIT == 32:
- long_dtype = W_Int32Dtype
- ulong_dtype = W_UInt32Dtype
-elif LONG_BIT == 64:
- long_dtype = W_Int64Dtype
- ulong_dtype = W_UInt64Dtype
-else:
- assert False
-
-class W_LongDtype(long_dtype):
- num = 7
- aliases = ["l"]
- applevel_types = ["int"]
-
-class W_ULongDtype(ulong_dtype):
- num = 8
- aliases = ["L"]
-
-W_Float32Dtype = create_low_level_dtype(
- num = 11, kind = FLOATINGLTR, name = "float32",
- aliases = ["f", "float32", "f4"],
- applevel_types = [],
- T = lltype.SingleFloat,
- valtype = rarithmetic.r_singlefloat,
- expected_size = 4,
-)
-class W_Float32Dtype(FloatArithmeticDtype, W_Float32Dtype):
- pass
-
-W_Float64Dtype = create_low_level_dtype(
- num = 12, kind = FLOATINGLTR, name = "float64",
- aliases = ["d", "float64", "f8"],
- applevel_types = ["float"],
- T = lltype.Float,
- valtype = float,
- expected_size = 8,
-)
-class W_Float64Dtype(FloatArithmeticDtype, W_Float64Dtype):
- pass
-
-ALL_DTYPES = [
- W_BoolDtype,
- W_Int8Dtype, W_UInt8Dtype, W_Int16Dtype, W_UInt16Dtype,
- W_Int32Dtype, W_UInt32Dtype, W_LongDtype, W_ULongDtype,
- W_Int64Dtype, W_UInt64Dtype,
- W_Float32Dtype, W_Float64Dtype,
-]
-
-dtypes_by_alias = unrolling_iterable([
- (alias, dtype)
- for dtype in ALL_DTYPES
- for alias in dtype.aliases
-])
-dtypes_by_apptype = unrolling_iterable([
- (apptype, dtype)
- for dtype in ALL_DTYPES
- for apptype in dtype.applevel_types
-])
-dtypes_by_num_bytes = unrolling_iterable(sorted([
- (dtype.num_bytes, dtype)
- for dtype in ALL_DTYPES
-]))
-
W_Dtype.typedef = TypeDef("dtype",
- __module__ = "numpy",
+ __module__ = "numpypy",
__new__ = interp2app(W_Dtype.descr__new__.im_func),
+ __str__= interp2app(W_Dtype.descr_str),
__repr__ = interp2app(W_Dtype.descr_repr),
- __str__ = interp2app(W_Dtype.descr_str),
num = interp_attrproperty("num", cls=W_Dtype),
kind = interp_attrproperty("kind", cls=W_Dtype),
- itemsize = interp_attrproperty("num_bytes", cls=W_Dtype),
+ type = interp_attrproperty_w("w_box_type", cls=W_Dtype),
+ itemsize = GetSetProperty(W_Dtype.descr_get_itemsize),
shape = GetSetProperty(W_Dtype.descr_get_shape),
)
W_Dtype.typedef.acceptable_as_base_class = False
+
+class DtypeCache(object):
+ def __init__(self, space):
+ self.w_booldtype = W_Dtype(
+ types.Bool(),
+ num=0,
+ kind=BOOLLTR,
+ name="bool",
+ char="?",
+ w_box_type = space.gettypefor(interp_boxes.W_BoolBox),
+ alternate_constructors=[space.w_bool],
+ )
+ self.w_int8dtype = W_Dtype(
+ types.Int8(),
+ num=1,
+ kind=SIGNEDLTR,
+ name="int8",
+ char="b",
+ w_box_type = space.gettypefor(interp_boxes.W_Int8Box)
+ )
+ self.w_uint8dtype = W_Dtype(
+ types.UInt8(),
+ num=2,
+ kind=UNSIGNEDLTR,
+ name="uint8",
+ char="B",
+ w_box_type = space.gettypefor(interp_boxes.W_UInt8Box),
+ )
+ self.w_int16dtype = W_Dtype(
+ types.Int16(),
+ num=3,
+ kind=SIGNEDLTR,
+ name="int16",
+ char="h",
+ w_box_type = space.gettypefor(interp_boxes.W_Int16Box),
+ )
+ self.w_uint16dtype = W_Dtype(
+ types.UInt16(),
+ num=4,
+ kind=UNSIGNEDLTR,
+ name="uint16",
+ char="H",
+ w_box_type = space.gettypefor(interp_boxes.W_UInt16Box),
+ )
+ self.w_int32dtype = W_Dtype(
+ types.Int32(),
+ num=5,
+ kind=SIGNEDLTR,
+ name="int32",
+ char="i",
+ w_box_type = space.gettypefor(interp_boxes.W_Int32Box),
+ )
+ self.w_uint32dtype = W_Dtype(
+ types.UInt32(),
+ num=6,
+ kind=UNSIGNEDLTR,
+ name="uint32",
+ char="I",
+ w_box_type = space.gettypefor(interp_boxes.W_UInt32Box),
+ )
+ if LONG_BIT == 32:
+ name = "int32"
+ elif LONG_BIT == 64:
+ name = "int64"
+ self.w_longdtype = W_Dtype(
+ types.Long(),
+ num=7,
+ kind=SIGNEDLTR,
+ name=name,
+ char="l",
+ w_box_type = space.gettypefor(interp_boxes.W_LongBox),
+ alternate_constructors=[space.w_int],
+ )
+ self.w_ulongdtype = W_Dtype(
+ types.ULong(),
+ num=8,
+ kind=UNSIGNEDLTR,
+ name="u" + name,
+ char="L",
+ w_box_type = space.gettypefor(interp_boxes.W_ULongBox),
+ )
+ self.w_int64dtype = W_Dtype(
+ types.Int64(),
+ num=9,
+ kind=SIGNEDLTR,
+ name="int64",
+ char="q",
+ w_box_type = space.gettypefor(interp_boxes.W_Int64Box),
+ alternate_constructors=[space.w_long],
+ )
+ self.w_uint64dtype = W_Dtype(
+ types.UInt64(),
+ num=10,
+ kind=UNSIGNEDLTR,
+ name="uint64",
+ char="Q",
+ w_box_type = space.gettypefor(interp_boxes.W_UInt64Box),
+ )
+ self.w_float32dtype = W_Dtype(
+ types.Float32(),
+ num=11,
+ kind=FLOATINGLTR,
+ name="float32",
+ char="f",
+ w_box_type = space.gettypefor(interp_boxes.W_Float32Box),
+ )
+ self.w_float64dtype = W_Dtype(
+ types.Float64(),
+ num=12,
+ kind=FLOATINGLTR,
+ name="float64",
+ char="d",
+ w_box_type = space.gettypefor(interp_boxes.W_Float64Box),
+ alternate_constructors=[space.w_float],
+ )
+
+ self.builtin_dtypes = [
+ self.w_booldtype, self.w_int8dtype, self.w_uint8dtype,
+ 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.dtypes_by_num_bytes = sorted(
+ (dtype.itemtype.get_element_size(), dtype)
+ for dtype in self.builtin_dtypes
+ )
+
+def get_dtype_cache(space):
+ return space.fromcache(DtypeCache)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -98,47 +98,6 @@
endshape[i] = remainder[i]
return endshape
-def descr_new_array(space, w_subtype, w_item_or_iterable, w_dtype=None,
- w_order=NoneNotWrapped):
- # find scalar
- if not space.issequence_w(w_item_or_iterable):
- if space.is_w(w_dtype, space.w_None):
- w_dtype = interp_ufuncs.find_dtype_for_scalar(space,
- w_item_or_iterable)
- dtype = space.interp_w(interp_dtype.W_Dtype,
- space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
- )
- return scalar_w(space, dtype, w_item_or_iterable)
- if w_order is None:
- order = 'C'
- else:
- order = space.str_w(w_order)
- if order != 'C': # or order != 'F':
- raise operationerrfmt(space.w_ValueError, "Unknown order: %s",
- order)
- shape, elems_w = _find_shape_and_elems(space, w_item_or_iterable)
- # they come back in C order
- size = len(elems_w)
- if space.is_w(w_dtype, space.w_None):
- w_dtype = None
- for w_elem in elems_w:
- w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
- w_dtype)
- if w_dtype is space.fromcache(interp_dtype.W_Float64Dtype):
- break
- if w_dtype is None:
- w_dtype = space.w_None
- dtype = space.interp_w(interp_dtype.W_Dtype,
- space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
- )
- arr = NDimArray(size, shape[:], dtype=dtype, order=order)
- shapelen = len(shape)
- arr_iter = arr.start_iter(arr.shape)
- for i in range(len(elems_w)):
- w_elem = elems_w[i]
- dtype.setitem_w(space, arr.storage, arr_iter.offset, w_elem)
- arr_iter = arr_iter.next(shapelen)
- return arr
# Iterators for arrays
# --------------------
@@ -378,6 +337,13 @@
def add_invalidates(self, other):
self.invalidates.append(other)
+ def descr__new__(space, w_subtype, w_size, w_dtype=None):
+ dtype = space.interp_w(interp_dtype.W_Dtype,
+ space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+ )
+ size, shape = _find_size_and_shape(space, w_size)
+ return space.wrap(W_NDimArray(size, shape[:], dtype=dtype))
+
def _unaryop_impl(ufunc_name):
def impl(self, space):
return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self])
@@ -451,8 +417,8 @@
self=self, dtype=dtype,
i=i, result=result, idx=idx,
cur_best=cur_best)
- new_best = getattr(dtype, op_name)(cur_best, self.eval(i))
- if dtype.ne(new_best, cur_best):
+ new_best = getattr(dtype.itemtype, op_name)(cur_best, self.eval(i))
+ if dtype.itemtype.ne(new_best, cur_best):
result = idx
cur_best = new_best
i = i.next(shapelen)
@@ -462,8 +428,7 @@
size = self.find_size()
if size == 0:
raise OperationError(space.w_ValueError,
- space.wrap("Can't call %s on zero-size arrays" \
- % op_name))
+ space.wrap("Can't call %s on zero-size arrays" % op_name))
return space.wrap(loop(self))
return func_with_new_name(impl, "reduce_arg%s_impl" % op_name)
@@ -475,7 +440,7 @@
all_driver.jit_merge_point(signature=self.signature,
shapelen=shapelen, self=self,
dtype=dtype, i=i)
- if not dtype.bool(self.eval(i)):
+ if not dtype.itemtype.bool(self.eval(i)):
return False
i = i.next(shapelen)
return True
@@ -490,7 +455,7 @@
any_driver.jit_merge_point(signature=self.signature,
shapelen=shapelen, self=self,
dtype=dtype, i=i)
- if dtype.bool(self.eval(i)):
+ if dtype.itemtype.bool(self.eval(i)):
return True
i = i.next(shapelen)
return False
@@ -542,8 +507,8 @@
res.append(')')
else:
concrete.to_str(space, 1, res, indent=' ')
- if (dtype is not space.fromcache(interp_dtype.W_Float64Dtype) and
- dtype is not space.fromcache(interp_dtype.W_Int64Dtype)) or \
+ if (dtype is not interp_dtype.get_dtype_cache(space).w_float64dtype and
+ dtype is not interp_dtype.get_dtype_cache(space).w_int64dtype) or \
not self.find_size():
res.append(", dtype=" + dtype.name)
res.append(")")
@@ -612,7 +577,7 @@
start = False
else:
builder.append(spacer)
- builder.append(dtype.str_format(self.getitem(item)))
+ builder.append(dtype.itemtype.str_format(self.getitem(item)))
item += self.strides[0]
# Add a comma only if comma is False - this prevents adding two
# commas
@@ -625,7 +590,7 @@
start = False
else:
builder.append(spacer)
- builder.append(dtype.str_format(self.getitem(item)))
+ builder.append(dtype.itemtype.str_format(self.getitem(item)))
item += self.strides[0]
i += 1
else:
@@ -712,7 +677,7 @@
raise OperationError(space.w_IndexError, space.wrap(
"0-d arrays can't be indexed"))
item = concrete._index_of_single_item(space, w_idx)
- return concrete.getitem(item).wrap(space)
+ return concrete.getitem(item)
chunks = self._prepare_slice_args(space, w_idx)
return space.wrap(self.create_slice(space, chunks))
@@ -771,14 +736,15 @@
shape[:])
def descr_mean(self, space):
- return space.wrap(space.float_w(self.descr_sum(space)) / self.find_size())
+ return space.div(self.descr_sum(space), space.wrap(self.find_size()))
def descr_nonzero(self, space):
if self.find_size() > 1:
raise OperationError(space.w_ValueError, space.wrap(
"The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"))
- return space.wrap(space.is_true(self.get_concrete().eval(
- self.start_iter(self.shape)).wrap(space)))
+ return space.wrap(space.is_true(
+ self.get_concrete().eval(self.start_iter(self.shape))
+ ))
def descr_get_transpose(self, space):
concrete = self.get_concrete()
@@ -814,17 +780,14 @@
return w_obj
elif space.issequence_w(w_obj):
# Convert to array.
- w_obj = space.call_function(space.gettypefor(BaseArray), w_obj)
- assert isinstance(w_obj, BaseArray)
- return w_obj
+ return array(space, w_obj, w_order=None)
else:
# If it's a scalar
dtype = interp_ufuncs.find_dtype_for_scalar(space, w_obj)
return scalar_w(space, dtype, w_obj)
def scalar_w(space, dtype, w_obj):
- assert isinstance(dtype, interp_dtype.W_Dtype)
- return Scalar(dtype, dtype.unwrap(space, w_obj))
+ return Scalar(dtype, dtype.coerce(space, w_obj))
class Scalar(BaseArray):
"""
@@ -835,6 +798,7 @@
_attrs_ = ["dtype", "value", "shape"]
def __init__(self, dtype, value):
+ self.shape = self.strides = []
BaseArray.__init__(self, [], 'C')
self.dtype = dtype
self.value = value
@@ -858,7 +822,7 @@
return ConstantIterator()
def to_str(self, space, comma, builder, indent=' ', use_ellipsis=False):
- builder.append(self.dtype.str_format(self.value))
+ builder.append(self.dtype.itemtype.str_format(self.value))
def copy(self):
return Scalar(self.dtype, self.value)
@@ -884,7 +848,7 @@
i = 0
signature = self.signature
result_size = self.find_size()
- result = NDimArray(result_size, self.shape, self.find_dtype())
+ result = W_NDimArray(result_size, self.shape, self.find_dtype())
shapelen = len(self.shape)
i = self.start_iter()
ri = result.start_iter()
@@ -1111,14 +1075,14 @@
return 'Slice(%s)' % self.parent.debug_repr()
def copy(self):
- array = NDimArray(self.size, self.shape[:], self.find_dtype())
+ array = W_NDimArray(self.size, self.shape[:], self.find_dtype())
iter = self.start_iter()
while not iter.done():
array.setitem(iter.offset, self.getitem(iter.offset))
iter = iter.next(len(self.shape))
return array
-class NDimArray(BaseArray):
+class W_NDimArray(BaseArray):
""" A class representing contiguous array. We know that each iteration
by say ufunc will increase the data index by one
"""
@@ -1145,11 +1109,11 @@
return self.dtype.getitem(self.storage, iter.get_offset())
def copy(self):
- array = NDimArray(self.size, self.shape[:], self.dtype, self.order)
+ array = W_NDimArray(self.size, self.shape[:], self.dtype, self.order)
rffi.c_memcpy(
- rffi.cast(rffi.VOIDP, array.storage),
- rffi.cast(rffi.VOIDP, self.storage),
- self.size * self.dtype.num_bytes
+ array.storage,
+ self.storage,
+ self.size * self.dtype.itemtype.get_element_size()
)
return array
@@ -1160,8 +1124,7 @@
"len() of unsized object"))
def setitem_w(self, space, item, w_value):
- self.invalidated()
- self.dtype.setitem_w(space, self.storage, item, w_value)
+ return self.setitem(item, self.dtype.coerce(space, w_value))
def setitem(self, item, value):
self.invalidated()
@@ -1193,20 +1156,62 @@
shape.append(item)
return size, shape
+def array(space, w_item_or_iterable, w_dtype=None, w_order=NoneNotWrapped):
+ # find scalar
+ if not space.issequence_w(w_item_or_iterable):
+ if space.is_w(w_dtype, space.w_None):
+ w_dtype = interp_ufuncs.find_dtype_for_scalar(space,
+ w_item_or_iterable)
+ dtype = space.interp_w(interp_dtype.W_Dtype,
+ space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+ )
+ return scalar_w(space, dtype, w_item_or_iterable)
+ if w_order is None:
+ order = 'C'
+ else:
+ order = space.str_w(w_order)
+ if order != 'C': # or order != 'F':
+ raise operationerrfmt(space.w_ValueError, "Unknown order: %s",
+ order)
+ shape, elems_w = _find_shape_and_elems(space, w_item_or_iterable)
+ # they come back in C order
+ size = len(elems_w)
+ if space.is_w(w_dtype, space.w_None):
+ w_dtype = None
+ for w_elem in elems_w:
+ w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_elem,
+ w_dtype)
+ if w_dtype is interp_dtype.get_dtype_cache(space).w_float64dtype:
+ break
+ if w_dtype is None:
+ w_dtype = space.w_None
+ dtype = space.interp_w(interp_dtype.W_Dtype,
+ space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+ )
+ arr = W_NDimArray(size, shape[:], dtype=dtype, order=order)
+ shapelen = len(shape)
+ arr_iter = arr.start_iter(arr.shape)
+ for i in range(len(elems_w)):
+ w_elem = elems_w[i]
+ dtype.setitem(arr.storage, arr_iter.offset, dtype.coerce(space, w_elem))
+ arr_iter = arr_iter.next(shapelen)
+ return arr
+
def zeros(space, w_size, w_dtype=None):
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
)
size, shape = _find_size_and_shape(space, w_size)
- return space.wrap(NDimArray(size, shape[:], dtype=dtype))
+ return space.wrap(W_NDimArray(size, shape[:], dtype=dtype))
def ones(space, w_size, w_dtype=None):
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
)
+
size, shape = _find_size_and_shape(space, w_size)
- arr = NDimArray(size, shape[:], dtype=dtype)
- one = dtype.adapt_val(1)
+ arr = W_NDimArray(size, shape[:], dtype=dtype)
+ one = dtype.box(1)
arr.dtype.fill(arr.storage, one, 0, size)
return space.wrap(arr)
@@ -1217,9 +1222,9 @@
return w_arr.descr_dot(space, w_obj2)
BaseArray.typedef = TypeDef(
- 'numarray',
- __new__ = interp2app(descr_new_array),
-
+ 'ndarray',
+ __module__ = "numpypy",
+ __new__ = interp2app(BaseArray.descr__new__.im_func),
__len__ = interp2app(BaseArray.descr_len),
__getitem__ = interp2app(BaseArray.descr_getitem),
@@ -1308,10 +1313,10 @@
def descr_next(self, space):
if self.iter.done():
- raise OperationError(space.w_StopIteration, space.wrap(''))
+ raise OperationError(space.w_StopIteration, space.w_None)
result = self.eval(self.iter)
self.iter = self.iter.next(self.shapelen)
- return result.wrap(space)
+ return result
def descr_iter(self):
return self
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -1,6 +1,6 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
from pypy.rlib.rstruct.runpack import runpack
from pypy.rpython.lltypesystem import lltype, rffi
@@ -9,7 +9,7 @@
@unwrap_spec(s=str)
def fromstring(space, s):
- from pypy.module.micronumpy.interp_numarray import NDimArray
+ from pypy.module.micronumpy.interp_numarray import W_NDimArray
length = len(s)
if length % FLOAT_SIZE == 0:
@@ -18,8 +18,8 @@
raise OperationError(space.w_ValueError, space.wrap(
"string length %d not divisable by %d" % (length, FLOAT_SIZE)))
- dtype = space.fromcache(W_Float64Dtype)
- a = NDimArray(number, [number], dtype=dtype)
+ dtype = get_dtype_cache(space).w_float64dtype
+ a = W_NDimArray(number, [number], dtype=dtype)
start = 0
end = FLOAT_SIZE
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
@@ -2,7 +2,7 @@
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
-from pypy.module.micronumpy import interp_dtype, signature
+from pypy.module.micronumpy import interp_boxes, interp_dtype, signature, types
from pypy.rlib import jit
from pypy.rlib.rarithmetic import LONG_BIT
from pypy.tool.sourcetools import func_with_new_name
@@ -15,6 +15,7 @@
class W_Ufunc(Wrappable):
_attrs_ = ["name", "promote_to_float", "promote_bools", "identity"]
+ _immutable_fields_ = ["promote_to_float", "promote_bools"]
def __init__(self, name, promote_to_float, promote_bools, identity):
self.name = name
@@ -29,7 +30,7 @@
def descr_get_identity(self, space):
if self.identity is None:
return space.w_None
- return self.identity.wrap(space)
+ return self.identity
def descr_call(self, space, __args__):
if __args__.keywords or len(__args__.arguments_w) < self.argcount:
@@ -80,8 +81,7 @@
new_sig = signature.Signature.find_sig([
self.reduce_signature, obj.signature
])
- return self.reduce_loop(new_sig, shapelen, start, value, obj,
- dtype).wrap(space)
+ return self.reduce_loop(new_sig, shapelen, start, value, obj, dtype)
def reduce_loop(self, signature, shapelen, i, value, obj, dtype):
while not i.done():
@@ -115,7 +115,7 @@
promote_bools=self.promote_bools,
)
if isinstance(w_obj, Scalar):
- return self.func(res_dtype, w_obj.value.convert_to(res_dtype)).wrap(space)
+ return self.func(res_dtype, w_obj.value.convert_to(res_dtype))
new_sig = signature.Signature.find_sig([self.signature, w_obj.signature])
w_res = Call1(new_sig, w_obj.shape, res_dtype, w_obj, w_obj.order)
@@ -124,6 +124,7 @@
class W_Ufunc2(W_Ufunc):
+ _immutable_fields_ = ["comparison_func", "func"]
argcount = 2
def __init__(self, func, name, promote_to_float=False, promote_bools=False,
@@ -148,14 +149,14 @@
promote_bools=self.promote_bools,
)
if self.comparison_func:
- res_dtype = space.fromcache(interp_dtype.W_BoolDtype)
+ res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
else:
res_dtype = calc_dtype
if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar):
return self.func(calc_dtype,
w_lhs.value.convert_to(calc_dtype),
w_rhs.value.convert_to(calc_dtype)
- ).wrap(space)
+ )
new_sig = signature.Signature.find_sig([
self.signature, w_lhs.signature, w_rhs.signature
@@ -169,7 +170,7 @@
W_Ufunc.typedef = TypeDef("ufunc",
- __module__ = "numpy",
+ __module__ = "numpypy",
__call__ = interp2app(W_Ufunc.descr_call),
__repr__ = interp2app(W_Ufunc.descr_repr),
@@ -187,7 +188,7 @@
dt1, dt2 = dt2, dt1
# Some operations promote op(bool, bool) to return int8, rather than bool
if promote_bools and (dt1.kind == dt2.kind == interp_dtype.BOOLLTR):
- return space.fromcache(interp_dtype.W_Int8Dtype)
+ return interp_dtype.get_dtype_cache(space).w_int8dtype
if promote_to_float:
return find_unaryop_result_dtype(space, dt2, promote_to_float=True)
# If they're the same kind, choose the greater one.
@@ -197,14 +198,14 @@
# Everything promotes to float, and bool promotes to everything.
if dt2.kind == interp_dtype.FLOATINGLTR or dt1.kind == interp_dtype.BOOLLTR:
# Float32 + 8-bit int = Float64
- if dt2.num == 11 and dt1.num_bytes >= 4:
- return space.fromcache(interp_dtype.W_Float64Dtype)
+ if dt2.num == 11 and dt1.itemtype.get_element_size() >= 4:
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
return dt2
# for now this means mixing signed and unsigned
if dt2.kind == interp_dtype.SIGNEDLTR:
# if dt2 has a greater number of bytes, then just go with it
- if dt1.num_bytes < dt2.num_bytes:
+ if dt1.itemtype.get_element_size() < dt2.itemtype.get_element_size():
return dt2
# we need to promote both dtypes
dtypenum = dt2.num + 2
@@ -214,10 +215,11 @@
# UInt64 + signed = Float64
if dt2.num == 10:
dtypenum += 1
- newdtype = interp_dtype.ALL_DTYPES[dtypenum]
+ newdtype = interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
- if newdtype.num_bytes > dt2.num_bytes or newdtype.kind == interp_dtype.FLOATINGLTR:
- return space.fromcache(newdtype)
+ if (newdtype.itemtype.get_element_size() > dt2.itemtype.get_element_size() or
+ newdtype.kind == interp_dtype.FLOATINGLTR):
+ return newdtype
else:
# we only promoted to long on 32-bit or to longlong on 64-bit
# this is really for dealing with the Long and Ulong dtypes
@@ -225,35 +227,42 @@
dtypenum += 2
else:
dtypenum += 3
- return space.fromcache(interp_dtype.ALL_DTYPES[dtypenum])
+ return interp_dtype.get_dtype_cache(space).builtin_dtypes[dtypenum]
def find_unaryop_result_dtype(space, dt, promote_to_float=False,
promote_bools=False, promote_to_largest=False):
if promote_bools and (dt.kind == interp_dtype.BOOLLTR):
- return space.fromcache(interp_dtype.W_Int8Dtype)
+ return interp_dtype.get_dtype_cache(space).w_int8dtype
if promote_to_float:
if dt.kind == interp_dtype.FLOATINGLTR:
return dt
if dt.num >= 5:
- return space.fromcache(interp_dtype.W_Float64Dtype)
- for bytes, dtype in interp_dtype.dtypes_by_num_bytes:
- if dtype.kind == interp_dtype.FLOATINGLTR and dtype.num_bytes > dt.num_bytes:
- return space.fromcache(dtype)
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
+ for bytes, dtype in interp_dtype.get_dtype_cache(space).dtypes_by_num_bytes:
+ if (dtype.kind == interp_dtype.FLOATINGLTR and
+ dtype.itemtype.get_element_size() > dt.itemtype.get_element_size()):
+ return dtype
if promote_to_largest:
if dt.kind == interp_dtype.BOOLLTR or dt.kind == interp_dtype.SIGNEDLTR:
- return space.fromcache(interp_dtype.W_Int64Dtype)
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
elif dt.kind == interp_dtype.FLOATINGLTR:
- return space.fromcache(interp_dtype.W_Float64Dtype)
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
elif dt.kind == interp_dtype.UNSIGNEDLTR:
- return space.fromcache(interp_dtype.W_UInt64Dtype)
+ return interp_dtype.get_dtype_cache(space).w_uint64dtype
else:
assert False
return dt
def find_dtype_for_scalar(space, w_obj, current_guess=None):
- bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
- long_dtype = space.fromcache(interp_dtype.W_LongDtype)
- int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype)
+ 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
+
+ if isinstance(w_obj, interp_boxes.W_GenericBox):
+ dtype = w_obj.get_dtype(space)
+ if current_guess is None:
+ return dtype
+ return find_binop_result_dtype(space, dtype, current_guess)
if space.isinstance_w(w_obj, space.w_bool):
if current_guess is None or current_guess is bool_dtype:
@@ -269,20 +278,19 @@
current_guess is long_dtype or current_guess is int64_dtype):
return int64_dtype
return current_guess
- return space.fromcache(interp_dtype.W_Float64Dtype)
+ return interp_dtype.get_dtype_cache(space).w_float64dtype
def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
if argcount == 1:
def impl(res_dtype, value):
- return getattr(res_dtype, op_name)(value)
+ return getattr(res_dtype.itemtype, op_name)(value)
elif argcount == 2:
+ dtype_cache = interp_dtype.get_dtype_cache(space)
def impl(res_dtype, lvalue, rvalue):
- res = getattr(res_dtype, op_name)(lvalue, rvalue)
+ res = getattr(res_dtype.itemtype, op_name)(lvalue, rvalue)
if comparison_func:
- booldtype = space.fromcache(interp_dtype.W_BoolDtype)
- assert isinstance(booldtype, interp_dtype.W_BoolDtype)
- res = booldtype.box(res)
+ return dtype_cache.w_booldtype.box(res)
return res
return func_with_new_name(impl, ufunc_name)
@@ -338,7 +346,7 @@
identity = extra_kwargs.get("identity")
if identity is not None:
- identity = space.fromcache(interp_dtype.W_LongDtype).adapt_val(identity)
+ identity = interp_dtype.get_dtype_cache(space).w_longdtype.box(identity)
extra_kwargs["identity"] = identity
func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -1,6 +1,6 @@
from pypy.conftest import gettestobjspace
-from pypy.module.micronumpy import interp_dtype
-from pypy.module.micronumpy.interp_numarray import NDimArray, Scalar
+from pypy.module.micronumpy.interp_dtype import get_dtype_cache
+from pypy.module.micronumpy.interp_numarray import W_NDimArray, Scalar
from pypy.module.micronumpy.interp_ufuncs import (find_binop_result_dtype,
find_unaryop_result_dtype)
@@ -11,9 +11,10 @@
class TestSignature(object):
def test_binop_signature(self, space):
- float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+ float64_dtype = get_dtype_cache(space).w_float64dtype
+ bool_dtype = get_dtype_cache(space).w_booldtype
- ar = NDimArray(10, [10], dtype=float64_dtype)
+ ar = W_NDimArray(10, [10], dtype=float64_dtype)
v1 = ar.descr_add(space, ar)
v2 = ar.descr_add(space, Scalar(float64_dtype, 2.0))
assert v1.signature is not v2.signature
@@ -22,7 +23,7 @@
v4 = ar.descr_add(space, ar)
assert v1.signature is v4.signature
- bool_ar = NDimArray(10, [10], dtype=space.fromcache(interp_dtype.W_BoolDtype))
+ bool_ar = W_NDimArray(10, [10], dtype=bool_dtype)
v5 = ar.descr_add(space, bool_ar)
assert v5.signature is not v1.signature
assert v5.signature is not v2.signature
@@ -30,7 +31,9 @@
assert v5.signature is v6.signature
def test_slice_signature(self, space):
- ar = NDimArray(10, [10], dtype=space.fromcache(interp_dtype.W_Float64Dtype))
+ float64_dtype = get_dtype_cache(space).w_float64dtype
+
+ ar = W_NDimArray(10, [10], dtype=float64_dtype)
v1 = ar.descr_getitem(space, space.wrap(slice(1, 3, 1)))
v2 = ar.descr_getitem(space, space.wrap(slice(4, 6, 1)))
assert v1.signature is v2.signature
@@ -41,10 +44,10 @@
class TestUfuncCoerscion(object):
def test_binops(self, space):
- bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
- int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype)
- int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype)
- float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+ bool_dtype = get_dtype_cache(space).w_booldtype
+ int8_dtype = get_dtype_cache(space).w_int8dtype
+ int32_dtype = get_dtype_cache(space).w_int32dtype
+ float64_dtype = get_dtype_cache(space).w_float64dtype
# Basic pairing
assert find_binop_result_dtype(space, bool_dtype, bool_dtype) is bool_dtype
@@ -62,19 +65,19 @@
assert find_binop_result_dtype(space, bool_dtype, float64_dtype, promote_to_float=True) is float64_dtype
def test_unaryops(self, space):
- bool_dtype = space.fromcache(interp_dtype.W_BoolDtype)
- int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype)
- uint8_dtype = space.fromcache(interp_dtype.W_UInt8Dtype)
- int16_dtype = space.fromcache(interp_dtype.W_Int16Dtype)
- uint16_dtype = space.fromcache(interp_dtype.W_UInt16Dtype)
- int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype)
- uint32_dtype = space.fromcache(interp_dtype.W_UInt32Dtype)
- long_dtype = space.fromcache(interp_dtype.W_LongDtype)
- ulong_dtype = space.fromcache(interp_dtype.W_ULongDtype)
- int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype)
- uint64_dtype = space.fromcache(interp_dtype.W_UInt64Dtype)
- float32_dtype = space.fromcache(interp_dtype.W_Float32Dtype)
- float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype)
+ bool_dtype = get_dtype_cache(space).w_booldtype
+ int8_dtype = get_dtype_cache(space).w_int8dtype
+ uint8_dtype = get_dtype_cache(space).w_uint8dtype
+ int16_dtype = get_dtype_cache(space).w_int16dtype
+ uint16_dtype = get_dtype_cache(space).w_uint16dtype
+ int32_dtype = get_dtype_cache(space).w_int32dtype
+ uint32_dtype = get_dtype_cache(space).w_uint32dtype
+ long_dtype = get_dtype_cache(space).w_longdtype
+ ulong_dtype = get_dtype_cache(space).w_ulongdtype
+ int64_dtype = get_dtype_cache(space).w_int64dtype
+ uint64_dtype = get_dtype_cache(space).w_uint64dtype
+ float32_dtype = get_dtype_cache(space).w_float32dtype
+ float64_dtype = get_dtype_cache(space).w_float64dtype
# Normal rules, everything returns itself
assert find_unaryop_result_dtype(space, bool_dtype) is bool_dtype
diff --git a/pypy/module/micronumpy/test/test_compile.py b/pypy/module/micronumpy/test/test_compile.py
--- a/pypy/module/micronumpy/test/test_compile.py
+++ b/pypy/module/micronumpy/test/test_compile.py
@@ -1,6 +1,9 @@
+import py
-import py
-from pypy.module.micronumpy.compile import *
+from pypy.module.micronumpy.compile import (numpy_compile, Assignment,
+ ArrayConstant, FloatConstant, Operator, Variable, RangeConstant, Execute,
+ FunctionCall, FakeSpace)
+
class TestCompiler(object):
def compile(self, code):
@@ -106,7 +109,7 @@
c -> 3
"""
interp = self.run(code)
- assert interp.results[-1].value.val == 9
+ assert interp.results[-1].value == 9
def test_array_getitem(self):
code = """
@@ -115,7 +118,7 @@
a + b -> 3
"""
interp = self.run(code)
- assert interp.results[0].value.val == 3 + 6
+ assert interp.results[0].value == 3 + 6
def test_range_getitem(self):
code = """
@@ -123,7 +126,7 @@
r -> 3
"""
interp = self.run(code)
- assert interp.results[0].value.val == 6
+ assert interp.results[0].value == 6
def test_sum(self):
code = """
@@ -132,7 +135,7 @@
r
"""
interp = self.run(code)
- assert interp.results[0].value.val == 15
+ assert interp.results[0].value.value == 15
def test_array_write(self):
code = """
@@ -141,7 +144,7 @@
a -> 3
"""
interp = self.run(code)
- assert interp.results[0].value.val == 15
+ assert interp.results[0].value == 15
def test_min(self):
interp = self.run("""
@@ -150,7 +153,7 @@
b = a + a
min(b)
""")
- assert interp.results[0].value.val == -24
+ assert interp.results[0].value.value == -24
def test_max(self):
interp = self.run("""
@@ -159,7 +162,7 @@
b = a + a
max(b)
""")
- assert interp.results[0].value.val == 256
+ assert interp.results[0].value.value == 256
def test_slice(self):
interp = self.run("""
@@ -167,7 +170,7 @@
b = a -> :
b -> 3
""")
- assert interp.results[0].value.val == 4
+ assert interp.results[0].value == 4
def test_slice_step(self):
interp = self.run("""
@@ -175,7 +178,7 @@
b = a -> ::2
b -> 3
""")
- assert interp.results[0].value.val == 6
+ assert interp.results[0].value == 6
def test_setslice(self):
interp = self.run("""
@@ -185,7 +188,7 @@
a[::3] = b
a -> 3
""")
- assert interp.results[0].value.val == 5
+ assert interp.results[0].value == 5
def test_slice2(self):
@@ -196,14 +199,14 @@
b = s1 + s2
b -> 3
""")
- assert interp.results[0].value.val == 15
+ assert interp.results[0].value == 15
def test_multidim_getitem(self):
interp = self.run("""
a = [[1,2]]
a -> 0 -> 1
""")
- assert interp.results[0].value.val == 2
+ assert interp.results[0].value == 2
def test_multidim_getitem_2(self):
interp = self.run("""
@@ -211,7 +214,7 @@
b = a + a
b -> 1 -> 1
""")
- assert interp.results[0].value.val == 8
+ assert interp.results[0].value == 8
def test_set_slice(self):
interp = self.run("""
@@ -220,7 +223,7 @@
b[:] = a + a
b -> 3
""")
- assert interp.results[0].value.val == 6
+ assert interp.results[0].value == 6
def test_set_slice2(self):
interp = self.run("""
@@ -231,4 +234,4 @@
a[0:30:3] = c
a -> 3
""")
- assert interp.results[0].value.val == 11
+ assert interp.results[0].value == 11
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
@@ -31,7 +31,7 @@
def test_repr_str(self):
from numpypy import dtype
- assert repr(dtype) == "<type 'numpy.dtype'>"
+ assert repr(dtype) == "<type 'numpypy.dtype'>"
d = dtype('?')
assert repr(d) == "dtype('bool')"
assert str(d) == "bool"
@@ -45,13 +45,13 @@
assert a[i] is True_
def test_copy_array_with_dtype(self):
- from numpypy import array, False_, True_
+ from numpypy import array, False_, True_, int64
a = array([0, 1, 2, 3], dtype=long)
# int on 64-bit, long in 32-bit
- assert is_valid_int(a[0])
+ assert isinstance(a[0], int64)
b = a.copy()
- assert is_valid_int(b[0])
+ assert isinstance(b[0], int64)
a = array([0, 1, 2, 3], dtype=bool)
assert a[0] is False_
@@ -73,17 +73,17 @@
assert a[i] is True_
def test_zeros_long(self):
- from numpypy import zeros
+ from numpypy import zeros, int64
a = zeros(10, dtype=long)
for i in range(10):
- assert is_valid_int(a[i])
+ assert isinstance(a[i], int64)
assert a[1] == 0
def test_ones_long(self):
- from numpypy import ones
+ from numpypy import ones, int64
a = ones(10, dtype=long)
for i in range(10):
- assert is_valid_int(a[i])
+ assert isinstance(a[i], int64)
assert a[1] == 1
def test_overflow(self):
@@ -166,3 +166,99 @@
# You can't subclass dtype
raises(TypeError, type, "Foo", (dtype,), {})
+
+class AppTestTypes(BaseNumpyAppTest):
+ def test_abstract_types(self):
+ import numpypy as numpy
+ raises(TypeError, numpy.generic, 0)
+ raises(TypeError, numpy.number, 0)
+ raises(TypeError, numpy.integer, 0)
+ exc = raises(TypeError, numpy.signedinteger, 0)
+ assert str(exc.value) == "cannot create 'numpypy.signedinteger' instances"
+
+ raises(TypeError, numpy.floating, 0)
+ raises(TypeError, numpy.inexact, 0)
+
+ def test_bool(self):
+ import numpypy as numpy
+
+ assert numpy.bool_.mro() == [numpy.bool_, numpy.generic, object]
+ assert numpy.bool_(3) is numpy.True_
+ assert numpy.bool_("") is numpy.False_
+ assert type(numpy.True_) is type(numpy.False_) is numpy.bool_
+
+ class X(numpy.bool_):
+ pass
+
+ assert type(X(True)) is numpy.bool_
+ assert X(True) is numpy.True_
+
+ def test_int8(self):
+ import numpypy as numpy
+
+ assert numpy.int8.mro() == [numpy.int8, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object]
+
+ a = numpy.array([1, 2, 3], numpy.int8)
+ assert type(a[1]) is numpy.int8
+ assert numpy.dtype("int8").type is numpy.int8
+
+ x = numpy.int8(128)
+ assert x == -128
+ assert x != 128
+ assert type(x) is numpy.int8
+ assert repr(x) == "-128"
+
+ assert type(int(x)) is int
+ assert int(x) == -128
+
+ def test_int16(self):
+ import numpypy as numpy
+
+ x = numpy.int16(3)
+ assert x == 3
+
+ def test_int32(self):
+ import numpypy as numpy
+
+ x = numpy.int32(23)
+ assert x == 23
+
+ def test_int_(self):
+ import numpypy as numpy
+
+ assert numpy.int_ is numpy.dtype(int).type
+ assert numpy.int_.mro() == [numpy.int_, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, int, object]
+
+ def test_int64(self):
+ import sys
+ import numpypy as numpy
+
+ if sys.maxint == 2 ** 63 -1:
+ assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, int, object]
+ else:
+ assert numpy.int64.mro() == [numpy.int64, numpy.signedinteger, numpy.integer, numpy.number, numpy.generic, object]
+
+ assert numpy.dtype(numpy.int64).type is numpy.int64
+ assert numpy.int64(3) == 3
+
+ def test_float64(self):
+ import numpypy as numpy
+
+ assert numpy.float64.mro() == [numpy.float64, numpy.floating, numpy.inexact, numpy.number, numpy.generic, float, object]
+
+ a = numpy.array([1, 2, 3], numpy.float64)
+ assert type(a[1]) is numpy.float64
+ assert numpy.dtype(float).type is numpy.float64
+
+ assert numpy.float64(2.0) == 2.0
+
+ def test_subclass_type(self):
+ import numpypy as numpy
+
+ class X(numpy.float64):
+ def m(self):
+ return self + 2
+
+ b = X(10)
+ assert type(b) is X
+ assert b.m() == 12
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -1,7 +1,7 @@
import py
from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
-from pypy.module.micronumpy.interp_numarray import NDimArray, shape_agreement
+from pypy.module.micronumpy.interp_numarray import W_NDimArray, shape_agreement
from pypy.module.micronumpy import signature
from pypy.interpreter.error import OperationError
from pypy.conftest import gettestobjspace
@@ -28,18 +28,18 @@
return self.space.newtuple(args_w)
def test_strides_f(self):
- a = NDimArray(100, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(100, [10, 5, 3], MockDtype(), 'F')
assert a.strides == [1, 10, 50]
assert a.backstrides == [9, 40, 100]
def test_strides_c(self):
- a = NDimArray(100, [10, 5, 3], MockDtype(), 'C')
+ a = W_NDimArray(100, [10, 5, 3], MockDtype(), 'C')
assert a.strides == [15, 3, 1]
assert a.backstrides == [135, 12, 2]
def test_create_slice_f(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
s = a.create_slice(space, [(3, 0, 0, 1)])
assert s.start == 3
assert s.strides == [10, 50]
@@ -58,7 +58,7 @@
def test_create_slice_c(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
s = a.create_slice(space, [(3, 0, 0, 1)])
assert s.start == 45
assert s.strides == [3, 1]
@@ -78,7 +78,7 @@
def test_slice_of_slice_f(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
s = a.create_slice(space, [(5, 0, 0, 1)])
assert s.start == 5
s2 = s.create_slice(space, [(3, 0, 0, 1)])
@@ -96,7 +96,7 @@
def test_slice_of_slice_c(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
s = a.create_slice(space, [(5, 0, 0, 1)])
assert s.start == 15 * 5
s2 = s.create_slice(space, [(3, 0, 0, 1)])
@@ -114,7 +114,7 @@
def test_negative_step_f(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
s = a.create_slice(space, [(9, -1, -2, 5)])
assert s.start == 9
assert s.strides == [-2, 10, 50]
@@ -122,14 +122,14 @@
def test_negative_step_c(self):
space = self.space
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), order='C')
s = a.create_slice(space, [(9, -1, -2, 5)])
assert s.start == 135
assert s.strides == [-30, 3, 1]
assert s.backstrides == [-120, 12, 2]
def test_index_of_single_item_f(self):
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'F')
r = a._index_of_single_item(self.space, self.newtuple(1, 2, 2))
assert r == 1 + 2 * 10 + 2 * 50
s = a.create_slice(self.space, [(0, 10, 1, 10), (2, 0, 0, 1)])
@@ -139,7 +139,7 @@
assert r == a._index_of_single_item(self.space, self.newtuple(1, 2, 1))
def test_index_of_single_item_c(self):
- a = NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
+ a = W_NDimArray(10 * 5 * 3, [10, 5, 3], MockDtype(), 'C')
r = a._index_of_single_item(self.space, self.newtuple(1, 2, 2))
assert r == 1 * 3 * 5 + 2 * 3 + 2
s = a.create_slice(self.space, [(0, 10, 1, 10), (2, 0, 0, 1)])
@@ -160,6 +160,21 @@
class AppTestNumArray(BaseNumpyAppTest):
+ def test_ndarray(self):
+ from numpypy import ndarray, array, dtype
+
+ assert type(ndarray) is type
+ assert type(array) is not type
+ a = ndarray((2, 3))
+ assert a.shape == (2, 3)
+ assert a.dtype == dtype(float)
+
+ raises(TypeError, ndarray, [[1], [2], [3]])
+
+ a = ndarray(3, dtype=int)
+ assert a.shape == (3,)
+ assert a.dtype is dtype(int)
+
def test_type(self):
from numpypy import array
ar = array(range(5))
@@ -359,11 +374,11 @@
assert r[i] == i + 3
def test_add_list(self):
- from numpypy import array
+ from numpypy import array, ndarray
a = array(range(5))
b = list(reversed(range(5)))
c = a + b
- assert isinstance(c, array)
+ assert isinstance(c, ndarray)
for i in range(5):
assert c[i] == 4
@@ -709,7 +724,7 @@
assert b[i] == 2.5 * a[i]
def test_dtype_guessing(self):
- from numpypy import array, dtype
+ from numpypy import array, dtype, float64, int8, bool_
assert array([True]).dtype is dtype(bool)
assert array([True, False]).dtype is dtype(bool)
@@ -719,6 +734,10 @@
assert array([1.2, True]).dtype is dtype(float)
assert array([1.2, 5]).dtype is dtype(float)
assert array([]).dtype is dtype(float)
+ assert array([float64(2)]).dtype is dtype(float)
+ assert array([int8(3)]).dtype is dtype("int8")
+ assert array([bool_(True)]).dtype is dtype(bool)
+ assert array([bool_(True), 3.0]).dtype is dtype(float)
def test_comparison(self):
import operator
@@ -1008,10 +1027,10 @@
b = a[0].copy()
assert (b == zeros(10)).all()
-class AppTestSupport(object):
+class AppTestSupport(BaseNumpyAppTest):
def setup_class(cls):
import struct
- cls.space = gettestobjspace(usemodules=('micronumpy',))
+ BaseNumpyAppTest.setup_class.im_func(cls)
cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
def test_fromstring(self):
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
@@ -8,7 +8,7 @@
assert isinstance(add, ufunc)
assert repr(add) == "<ufunc 'add'>"
- assert repr(ufunc) == "<type 'numpy.ufunc'>"
+ assert repr(ufunc) == "<type 'numpypy.ufunc'>"
def test_ufunc_attrs(self):
from numpypy import add, multiply, sin
@@ -37,36 +37,36 @@
assert minimum(2.0, 3.0) == 2.0
def test_sequence(self):
- from numpypy import array, negative, minimum
+ from numpypy import array, ndarray, negative, minimum
a = array(range(3))
b = [2.0, 1.0, 0.0]
c = 1.0
b_neg = negative(b)
- assert isinstance(b_neg, array)
+ assert isinstance(b_neg, ndarray)
for i in range(3):
assert b_neg[i] == -b[i]
min_a_b = minimum(a, b)
- assert isinstance(min_a_b, array)
+ assert isinstance(min_a_b, ndarray)
for i in range(3):
assert min_a_b[i] == min(a[i], b[i])
min_b_a = minimum(b, a)
- assert isinstance(min_b_a, array)
+ assert isinstance(min_b_a, ndarray)
for i in range(3):
assert min_b_a[i] == min(a[i], b[i])
min_a_c = minimum(a, c)
- assert isinstance(min_a_c, array)
+ assert isinstance(min_a_c, ndarray)
for i in range(3):
assert min_a_c[i] == min(a[i], c)
min_c_a = minimum(c, a)
- assert isinstance(min_c_a, array)
+ assert isinstance(min_c_a, ndarray)
for i in range(3):
assert min_c_a[i] == min(a[i], c)
min_b_c = minimum(b, c)
- assert isinstance(min_b_c, array)
+ assert isinstance(min_b_c, ndarray)
for i in range(3):
assert min_b_c[i] == min(b[i], c)
min_c_b = minimum(c, b)
- assert isinstance(min_c_b, array)
+ assert isinstance(min_c_b, ndarray)
for i in range(3):
assert min_c_b[i] == min(b[i], c)
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -8,11 +8,11 @@
from pypy.jit.metainterp import pyjitpl
from pypy.jit.metainterp.test.support import LLJitMixin
from pypy.jit.metainterp.warmspot import reset_stats
-from pypy.module.micronumpy import interp_ufuncs, signature
+from pypy.module.micronumpy import interp_boxes, interp_ufuncs, signature
from pypy.module.micronumpy.compile import (numpy_compile, FakeSpace,
FloatObject, IntObject, BoolObject, Parser, InterpreterState)
-from pypy.module.micronumpy.interp_numarray import NDimArray, NDimSlice,\
- BaseArray
+from pypy.module.micronumpy.interp_numarray import (W_NDimArray, NDimSlice,
+ BaseArray)
from pypy.rlib.nonconst import NonConstant
from pypy.rpython.annlowlevel import llstr, hlstr
@@ -48,17 +48,15 @@
def f(i):
interp = InterpreterState(codes[i])
interp.run(space)
- res = interp.results[-1]
- assert isinstance(res, BaseArray)
- w_res = res.eval(res.start_iter()).wrap(interp.space)
- if isinstance(w_res, BoolObject):
- return float(w_res.boolval)
- elif isinstance(w_res, FloatObject):
- return w_res.floatval
- elif isinstance(w_res, IntObject):
- return w_res.intval
- else:
- return -42.
+ w_res = interp.results[-1]
+ if isinstance(w_res, BaseArray):
+ w_res = w_res.eval(w_res.start_iter())
+
+ if isinstance(w_res, interp_boxes.W_Float64Box):
+ return w_res.value
+ elif isinstance(w_res, interp_boxes.W_BoolBox):
+ return float(w_res.value)
+ raise TypeError(w_res)
if self.graph is None:
interp, graph = self.meta_interp(f, [i],
@@ -80,9 +78,9 @@
def test_add(self):
result = self.run("add")
- self.check_simple_loop({'getarrayitem_raw': 2, 'float_add': 1,
- 'setarrayitem_raw': 1, 'int_add': 3,
- 'int_ge': 1, 'guard_false': 1, 'jump': 1})
+ self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+ 'setinteriorfield_raw': 1, 'int_add': 3,
+ 'int_ge': 1, 'guard_false': 1, 'jump': 1})
assert result == 3 + 3
def define_float_add():
@@ -94,9 +92,9 @@
def test_floatadd(self):
result = self.run("float_add")
assert result == 3 + 3
- self.check_simple_loop({"getarrayitem_raw": 1, "float_add": 1,
- "setarrayitem_raw": 1, "int_add": 2,
- "int_ge": 1, "guard_false": 1, "jump": 1})
+ self.check_simple_loop({"getinteriorfield_raw": 1, "float_add": 1,
+ "setinteriorfield_raw": 1, "int_add": 2,
+ "int_ge": 1, "guard_false": 1, "jump": 1})
def define_sum():
return """
@@ -108,9 +106,9 @@
def test_sum(self):
result = self.run("sum")
assert result == 2 * sum(range(30))
- self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 2,
- "int_add": 2,
- "int_ge": 1, "guard_false": 1, "jump": 1})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 2,
+ "int_add": 2, "int_ge": 1, "guard_false": 1,
+ "jump": 1})
def define_prod():
return """
@@ -125,9 +123,9 @@
for i in range(30):
expected *= i * 2
assert result == expected
- self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
- "float_mul": 1, "int_add": 2,
- "int_ge": 1, "guard_false": 1, "jump": 1})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+ "float_mul": 1, "int_add": 2,
+ "int_ge": 1, "guard_false": 1, "jump": 1})
def test_max(self):
py.test.skip("broken, investigate")
@@ -138,9 +136,9 @@
max(b)
""")
assert result == 256
- self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
- "float_mul": 1, "int_add": 1,
- "int_lt": 1, "guard_true": 1, "jump": 1})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+ "float_mul": 1, "int_add": 1,
+ "int_lt": 1, "guard_true": 1, "jump": 1})
def test_min(self):
py.test.skip("broken, investigate")
@@ -151,9 +149,9 @@
min(b)
""")
assert result == -24
- self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
- "float_mul": 1, "int_add": 1,
- "int_lt": 1, "guard_true": 1, "jump": 1})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+ "float_mul": 1, "int_add": 1,
+ "int_lt": 1, "guard_true": 1, "jump": 1})
def define_any():
return """
@@ -166,10 +164,10 @@
def test_any(self):
result = self.run("any")
assert result == 1
- self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1,
- "float_ne": 1, "int_add": 2,
- "int_ge": 1, "jump": 1,
- "guard_false": 2})
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1,
+ "float_ne": 1, "int_add": 2,
+ "int_ge": 1, "jump": 1,
+ "guard_false": 2})
def define_already_forced():
return """
@@ -188,10 +186,10 @@
# sure it was optimized correctly.
# XXX the comment above is wrong now. We need preferrably a way to
# count the two loops separately
- self.check_resops({'setarrayitem_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 35,
+ self.check_resops({'setinteriorfield_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 41,
'guard_class': 22, 'int_add': 8, 'float_mul': 2,
'guard_isnull': 2, 'jump': 4, 'int_ge': 4,
- 'getarrayitem_raw': 4, 'float_add': 2, 'guard_false': 4,
+ 'getinteriorfield_raw': 4, 'float_add': 2, 'guard_false': 4,
'guard_value': 2})
def define_ufunc():
@@ -205,10 +203,9 @@
def test_ufunc(self):
result = self.run("ufunc")
assert result == -6
- self.check_simple_loop({"getarrayitem_raw": 2, "float_add": 1, "float_neg": 1,
- "setarrayitem_raw": 1, "int_add": 3,
- "int_ge": 1, "guard_false": 1, "jump": 1,
- })
+ self.check_simple_loop({"getinteriorfield_raw": 2, "float_add": 1, "float_neg": 1,
+ "setinteriorfield_raw": 1, "int_add": 3,
+ "int_ge": 1, "guard_false": 1, "jump": 1})
def define_specialization():
return """
@@ -246,9 +243,9 @@
def test_slice(self):
result = self.run("slice")
assert result == 18
- self.check_simple_loop({'getarrayitem_raw': 2,
+ self.check_simple_loop({'getinteriorfield_raw': 2,
'float_add': 1,
- 'setarrayitem_raw': 1,
+ 'setinteriorfield_raw': 1,
'int_add': 3,
'int_ge': 1, 'guard_false': 1,
'jump': 1})
@@ -265,8 +262,8 @@
def test_slice2(self):
result = self.run("slice2")
assert result == 15
- self.check_simple_loop({'getarrayitem_raw': 2, 'float_add': 1,
- 'setarrayitem_raw': 1, 'int_add': 3,
+ self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
+ 'setinteriorfield_raw': 1, 'int_add': 3,
'int_ge': 1, 'guard_false': 1, 'jump': 1})
def define_multidim():
@@ -279,11 +276,11 @@
def test_multidim(self):
result = self.run('multidim')
assert result == 8
- self.check_simple_loop({'float_add': 1, 'getarrayitem_raw': 2,
- 'guard_false': 1, 'int_add': 3, 'int_ge': 1,
- 'jump': 1, 'setarrayitem_raw': 1})
# int_add might be 1 here if we try slightly harder with
# reusing indexes or some optimization
+ self.check_simple_loop({'float_add': 1, 'getinteriorfield_raw': 2,
+ 'guard_false': 1, 'int_add': 3, 'int_ge': 1,
+ 'jump': 1, 'setinteriorfield_raw': 1})
def define_multidim_slice():
return """
@@ -329,18 +326,18 @@
result = self.run("setslice")
assert result == 11.0
self.check_loop_count(1)
- self.check_simple_loop({'getarrayitem_raw': 2, 'float_add' : 1,
- 'setarrayitem_raw': 1, 'int_add': 3,
+ self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add' : 1,
+ 'setinteriorfield_raw': 1, 'int_add': 3,
'int_eq': 1, 'guard_false': 1, 'jump': 1})
class TestNumpyOld(LLJitMixin):
def setup_class(cls):
py.test.skip("old")
from pypy.module.micronumpy.compile import FakeSpace
- from pypy.module.micronumpy.interp_dtype import W_Float64Dtype
+ from pypy.module.micronumpy.interp_dtype import get_dtype_cache
cls.space = FakeSpace()
- cls.float64_dtype = cls.space.fromcache(W_Float64Dtype)
+ cls.float64_dtype = get_dtype_cache(cls.space).w_float64dtype
def test_int32_sum(self):
py.test.skip("pypy/jit/backend/llimpl.py needs to be changed to "
@@ -355,7 +352,7 @@
dtype = float64_dtype
else:
dtype = int32_dtype
- ar = NDimArray(n, [n], dtype=dtype)
+ ar = W_NDimArray(n, [n], dtype=dtype)
i = 0
while i < n:
ar.get_concrete().setitem(i, int32_dtype.box(7))
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/types.py
@@ -0,0 +1,389 @@
+import functools
+import math
+
+from pypy.module.micronumpy import interp_boxes
+from pypy.objspace.std.floatobject import float2string
+from pypy.rlib import rfloat, libffi, clibffi
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.rarithmetic import LONG_BIT, widen
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+def simple_unary_op(func):
+ specialize.argtype(1)(func)
+ @functools.wraps(func)
+ def dispatcher(self, v):
+ return self.box(
+ func(
+ self,
+ self.for_computation(self.unbox(v))
+ )
+ )
+ return dispatcher
+
+def simple_binary_op(func):
+ specialize.argtype(1, 2)(func)
+ @functools.wraps(func)
+ def dispatcher(self, v1, v2):
+ return self.box(
+ 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)
+ def dispatcher(self, v1, v2):
+ return func(self,
+ self.for_computation(self.unbox(v1)),
+ self.for_computation(self.unbox(v2))
+ )
+ return dispatcher
+
+class BaseType(object):
+ def _unimplemented_ufunc(self, *args):
+ raise NotImplementedError
+ # add = sub = mul = div = mod = pow = eq = ne = lt = le = gt = ge = max = \
+ # min = copysign = pos = neg = abs = sign = reciprocal = fabs = floor = \
+ # exp = sin = cos = tan = arcsin = arccos = arctan = arcsinh = \
+ # arctanh = _unimplemented_ufunc
+
+class Primitive(object):
+ _mixin_ = True
+ def get_element_size(self):
+ return rffi.sizeof(self.T)
+
+ @specialize.argtype(1)
+ def box(self, value):
+ return self.BoxType(rffi.cast(self.T, value))
+
+ def unbox(self, box):
+ assert isinstance(box, self.BoxType)
+ return box.value
+
+ def coerce(self, space, 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):
+ # XXX: ugly
+ w_obj = space.allocate_instance(self.BoxType, w_subtype)
+ assert isinstance(w_obj, self.BoxType)
+ w_obj.__init__(self._coerce(space, w_item).value)
+ return w_obj
+
+ def _coerce(self, space, w_item):
+ raise NotImplementedError
+
+ def read(self, storage, width, i, offset):
+ return self.box(libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
+ width, storage, i, offset
+ ))
+
+ def store(self, storage, width, i, offset, box):
+ value = self.unbox(box)
+ libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+ width, storage, i, offset, value
+ )
+
+ def fill(self, storage, width, box, start, stop, offset):
+ value = self.unbox(box)
+ for i in xrange(start, stop):
+ libffi.array_setitem(clibffi.cast_type_to_ffitype(self.T),
+ width, storage, i, offset, value
+ )
+
+ @simple_binary_op
+ def add(self, v1, v2):
+ return v1 + v2
+
+ @simple_binary_op
+ def sub(self, v1, v2):
+ return v1 - v2
+
+ @simple_binary_op
+ def mul(self, v1, v2):
+ return v1 * v2
+
+ @simple_unary_op
+ def pos(self, v):
+ return +v
+
+ @simple_unary_op
+ def neg(self, v):
+ return -v
+
+ @simple_unary_op
+ def abs(self, v):
+ return abs(v)
+
+ @raw_binary_op
+ def eq(self, v1, v2):
+ return v1 == v2
+
+ @raw_binary_op
+ def ne(self, v1, v2):
+ return v1 != v2
+
+ @raw_binary_op
+ def lt(self, v1, v2):
+ return v1 < v2
+
+ @raw_binary_op
+ def le(self, v1, v2):
+ return v1 <= v2
+
+ @raw_binary_op
+ def gt(self, v1, v2):
+ return v1 > v2
+
+ @raw_binary_op
+ def ge(self, v1, v2):
+ return v1 >= 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)
+
+class Bool(BaseType, Primitive):
+ T = lltype.Bool
+ BoxType = interp_boxes.W_BoolBox
+
+ True = BoxType(True)
+ False = BoxType(False)
+
+ @specialize.argtype(1)
+ def box(self, value):
+ box = Primitive.box(self, value)
+ if box.value:
+ return self.True
+ else:
+ return self.False
+
+ def coerce_subtype(self, space, w_subtype, w_item):
+ # Doesn't return subclasses so it can return the constants.
+ return self._coerce(space, w_item)
+
+ def _coerce(self, space, w_item):
+ return self.box(space.is_true(w_item))
+
+ def str_format(self, box):
+ value = self.unbox(box)
+ return "True" if value else "False"
+
+ def for_computation(self, v):
+ return int(v)
+
+class Integer(Primitive):
+ _mixin_ = True
+
+ def _coerce(self, space, w_item):
+ return self.box(space.int_w(space.int(w_item)))
+
+ def str_format(self, box):
+ value = self.unbox(box)
+ return str(self.for_computation(value))
+
+ def for_computation(self, v):
+ return widen(v)
+
+ @simple_binary_op
+ def div(self, v1, v2):
+ if v2 == 0:
+ return 0
+ return v1 / v2
+
+ @simple_binary_op
+ def mod(self, v1, v2):
+ return v1 % v2
+
+ @simple_binary_op
+ def pow(self, v1, v2):
+ res = 1
+ while v2 > 0:
+ if v2 & 1:
+ res *= v1
+ v2 >>= 1
+ if v2 == 0:
+ break
+ v1 *= v1
+ return res
+
+ @simple_unary_op
+ def sign(self, v):
+ if v > 0:
+ return 1
+ elif v < 0:
+ return -1
+ else:
+ assert v == 0
+ return 0
+
+class Int8(BaseType, Integer):
+ T = rffi.SIGNEDCHAR
+ BoxType = interp_boxes.W_Int8Box
+
+class UInt8(BaseType, Integer):
+ T = rffi.UCHAR
+ BoxType = interp_boxes.W_UInt8Box
+
+class Int16(BaseType, Integer):
+ T = rffi.SHORT
+ BoxType = interp_boxes.W_Int16Box
+
+class UInt16(BaseType, Integer):
+ T = rffi.USHORT
+ BoxType = interp_boxes.W_UInt16Box
+
+class Int32(BaseType, Integer):
+ T = rffi.INT
+ BoxType = interp_boxes.W_Int32Box
+
+class UInt32(BaseType, Integer):
+ T = rffi.UINT
+ BoxType = interp_boxes.W_UInt32Box
+
+class Long(BaseType, Integer):
+ T = rffi.LONG
+ BoxType = interp_boxes.W_LongBox
+
+class ULong(BaseType, Integer):
+ T = rffi.ULONG
+ BoxType = interp_boxes.W_ULongBox
+
+class Int64(BaseType, Integer):
+ T = rffi.LONGLONG
+ BoxType = interp_boxes.W_Int64Box
+
+class UInt64(BaseType, Integer):
+ T = rffi.ULONGLONG
+ BoxType = interp_boxes.W_UInt64Box
+
+class Float(Primitive):
+ _mixin_ = True
+
+ def _coerce(self, space, w_item):
+ return self.box(space.float_w(space.float(w_item)))
+
+ def str_format(self, box):
+ value = self.unbox(box)
+ return float2string(self.for_computation(value), "g", rfloat.DTSF_STR_PRECISION)
+
+ def for_computation(self, v):
+ return float(v)
+
+ @simple_binary_op
+ def div(self, v1, v2):
+ try:
+ return v1 / v2
+ except ZeroDivisionError:
+ if v1 == v2 == 0.0:
+ return rfloat.NAN
+ return rfloat.copysign(rfloat.INFINITY, v1 * v2)
+
+ @simple_binary_op
+ def mod(self, v1, v2):
+ return math.fmod(v1, v2)
+
+ @simple_binary_op
+ def pow(self, v1, v2):
+ return math.pow(v1, v2)
+
+ @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)
+
+ @simple_unary_op
+ def fabs(self, v):
+ return math.fabs(v)
+
+ @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 exp(self, v):
+ try:
+ return math.exp(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_unary_op
+ def arcsinh(self, v):
+ return math.asinh(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
+
+
+class Float32(BaseType, Float):
+ T = rffi.FLOAT
+ BoxType = interp_boxes.W_Float32Box
+
+class Float64(BaseType, Float):
+ T = rffi.DOUBLE
+ BoxType = interp_boxes.W_Float64Box
\ No newline at end of file
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -102,6 +102,7 @@
'instancetypedef',
'terminator',
'_version_tag?',
+ 'name?',
]
# for config.objspace.std.getattributeshortcut
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -738,3 +738,29 @@
return hop.genop('jit_marker', vlist,
resulttype=lltype.Void)
+def record_known_class(value, cls):
+ """
+ Assure the JIT that value is an instance of cls. This is not a precise
+ class check, unlike a guard_class.
+ """
+ assert isinstance(value, cls)
+
+
+class Entry(ExtRegistryEntry):
+ _about_ = record_known_class
+
+ def compute_result_annotation(self, s_inst, s_cls):
+ from pypy.annotation import model as annmodel
+ assert s_cls.is_constant()
+ assert not s_inst.can_be_none()
+ assert isinstance(s_inst, annmodel.SomeInstance)
+
+ def specialize_call(self, hop):
+ from pypy.rpython.lltypesystem import lltype, rclass
+ classrepr = rclass.get_type_repr(hop.rtyper)
+
+ hop.exception_cannot_occur()
+ v_inst = hop.inputarg(hop.args_r[0], arg=0)
+ v_cls = hop.inputarg(classrepr, arg=1)
+ return hop.genop('jit_record_known_class', [v_inst, v_cls],
+ resulttype=lltype.Void)
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -416,6 +416,10 @@
def getaddressindll(self, name):
return dlsym(self.lib, name)
+# These specialize.call_location's should really be specialize.arg(0), however
+# you can't hash a pointer obj, which the specialize machinery wants to do.
+# Given the present usage of these functions, it's good enough.
+ at specialize.call_location()
@jit.oopspec("libffi_array_getitem(ffitype, width, addr, index, offset)")
def array_getitem(ffitype, width, addr, index, offset):
for TYPE, ffitype2 in clibffi.ffitype_map:
@@ -425,6 +429,7 @@
return rffi.cast(rffi.CArrayPtr(TYPE), addr)[0]
assert False
+ at specialize.call_location()
@jit.oopspec("libffi_array_setitem(ffitype, width, addr, index, offset, value)")
def array_setitem(ffitype, width, addr, index, offset, value):
for TYPE, ffitype2 in clibffi.ffitype_map:
@@ -433,4 +438,4 @@
addr = rffi.ptradd(addr, offset)
rffi.cast(rffi.CArrayPtr(TYPE), addr)[0] = value
return
- assert False
\ No newline at end of file
+ assert False
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -91,9 +91,18 @@
return decorated_func
+ def call_location(self):
+ """ Specializes the function for each call site.
+ """
+ def decorated_func(func):
+ func._annspecialcase_ = "specialize:call_location"
+ return func
+
+ return decorated_func
+
def _wrap(self, args):
return "("+','.join([repr(arg) for arg in args]) +")"
-
+
specialize = _Specialize()
def enforceargs(*args):
@@ -125,7 +134,7 @@
def __hash__(self):
raise TypeError("Symbolics are not hashable!")
-
+
def __nonzero__(self):
raise TypeError("Symbolics are not comparable")
@@ -155,7 +164,7 @@
def lltype(self):
from pypy.rpython.lltypesystem import lltype
return lltype.Signed
-
+
malloc_zero_filled = CDefinedIntSymbolic('MALLOC_ZERO_FILLED', default=0)
running_on_llinterp = CDefinedIntSymbolic('RUNNING_ON_LLINTERP', default=1)
# running_on_llinterp is meant to have the value 0 in all backends
@@ -221,7 +230,7 @@
def compute_result_annotation(self, s_sizehint):
from pypy.annotation.model import SomeInteger
-
+
assert isinstance(s_sizehint, SomeInteger)
return self.bookkeeper.newlist()
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -548,6 +548,9 @@
def op_jit_marker(self, *args):
pass
+ def op_jit_record_known_class(self, *args):
+ pass
+
def op_get_exception_addr(self, *args):
raise NotImplementedError
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -430,6 +430,7 @@
'jit_force_virtual': LLOp(canrun=True),
'jit_is_virtual': LLOp(canrun=True),
'jit_force_quasi_immutable': LLOp(canrun=True),
+ 'jit_record_known_class' : LLOp(canrun=True),
'get_exception_addr': LLOp(),
'get_exc_value_addr': LLOp(),
'do_malloc_fixedsize_clear':LLOp(canmallocgc=True),
diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -555,6 +555,9 @@
def op_jit_force_quasi_immutable(*args):
pass
+def op_jit_record_known_class(x, y):
+ pass
+
def op_get_group_member(TYPE, grpptr, memberoffset):
from pypy.rpython.lltypesystem import llgroup
assert isinstance(memberoffset, llgroup.GroupMemberOffset)
diff --git a/pypy/translator/c/src/support.h b/pypy/translator/c/src/support.h
--- a/pypy/translator/c/src/support.h
+++ b/pypy/translator/c/src/support.h
@@ -11,6 +11,7 @@
#endif /* MIN */
#define RUNNING_ON_LLINTERP 0
+#define OP_JIT_RECORD_KNOWN_CLASS(i, c, r) /* nothing */
#define FAIL_EXCEPTION(exc, msg) \
{ \
More information about the pypy-commit
mailing list