Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r72311:6b30b8d83c24
Date: 2014-07-02 10:11 +0200
http://bitbucket.org/pypy/pypy/changeset/6b30b8d83c24/

Log:    Optimize array.extend() and make it support directly lists of ints
        or floats.

diff --git a/pypy/module/array/interp_array.py 
b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -674,6 +674,10 @@
                 return rffi.cast(mytype.itemtype, item)
             #
             # "regular" case: it fits in an rpython integer (lltype.Signed)
+            # or it is a float
+            return self.item_from_int_or_float(item)
+
+        def item_from_int_or_float(self, item):
             result = rffi.cast(mytype.itemtype, item)
             if mytype.canoverflow:
                 if rffi.cast(lltype.Signed, result) != item:
@@ -686,8 +690,8 @@
                                % mytype.bytes)
                     if not mytype.signed:
                         msg = 'un' + msg      # 'signed' => 'unsigned'
-                    raise OperationError(space.w_OverflowError,
-                                         space.wrap(msg))
+                    raise OperationError(self.space.w_OverflowError,
+                                         self.space.wrap(msg))
             return result
 
         def __del__(self):
@@ -734,27 +738,32 @@
         def fromsequence(self, w_seq):
             space = self.space
             oldlen = self.len
+            newlen = oldlen
             try:
-                new = space.len_w(w_seq)
-                self.setlen(self.len + new)
-            except OperationError:
-                pass
-
-            i = 0
-            try:
-                if mytype.typecode == 'u':
-                    myiter = space.unpackiterable
+                # optimized case for arrays of integers or floats
+                if mytype.unwrap == 'int_w':
+                    lst = space.listview_int(w_seq)
+                elif mytype.unwrap == 'float_w':
+                    lst = space.listview_float(w_seq)
                 else:
-                    myiter = space.listview
-                for w_i in myiter(w_seq):
-                    if oldlen + i >= self.len:
-                        self.setlen(oldlen + i + 1)
-                    self.buffer[oldlen + i] = self.item_w(w_i)
-                    i += 1
-            except OperationError:
-                self.setlen(oldlen + i)
-                raise
-            self.setlen(oldlen + i)
+                    lst = None
+                if lst is not None:
+                    self.setlen(oldlen + len(lst))
+                    buf = self.buffer
+                    for num in lst:
+                        buf[newlen] = self.item_from_int_or_float(num)
+                        newlen += 1
+                    return
+                #
+                # this is the general case
+                lst_w = space.listview(w_seq)
+                self.setlen(oldlen + len(lst_w))
+                for w_num in lst_w:
+                    self.buffer[newlen] = self.item_w(w_num)
+                    newlen += 1
+            finally:
+                if self.len != newlen:
+                    self.setlen(newlen)
 
         def extend(self, w_iterable, accept_different_array=False):
             space = self.space
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to