[Jython-checkins] jython: Faster extended slice deletion in bytearray.

jeff.allen jython-checkins at python.org
Thu Apr 9 09:28:36 CEST 2015


https://hg.python.org/jython/rev/d2824374b29a
changeset:   7649:d2824374b29a
parent:      7596:cf9ad15fca87
user:        Jeff Allen <ja.py at farowl.co.uk>
date:        Sun Feb 15 20:49:30 2015 +0000
summary:
  Faster extended slice deletion in bytearray.

Replace iterative deletion of single elements (causing repeat copy),
with a single-copy strategy approriate to the array implementation.
This is a perfromance loose-end in the original implementation.
Incidental code cleanup, particularly in JUnit test.

files:
  src/org/python/core/BaseBytes.java              |   19 +-
  src/org/python/core/PyByteArray.java            |  113 +---
  src/org/python/core/PySequence.java             |   80 +-
  src/org/python/core/SequenceIndexDelegate.java  |    9 +-
  tests/java/org/python/core/BaseBytesTest.java   |   92 +-
  tests/java/org/python/core/PyByteArrayTest.java |  233 ++++-----
  6 files changed, 243 insertions(+), 303 deletions(-)


diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java
--- a/src/org/python/core/BaseBytes.java
+++ b/src/org/python/core/BaseBytes.java
@@ -736,20 +736,10 @@
      */
     private class IndexDelegate extends PySequence.DefaultIndexDelegate {
 
-        /*
+        /**
          * bytearray treats assignment of a zero-length object to a slice as equivalent to deletion,
          * unlike list, even for an extended slice.
          */
-        // >>> a = range(10)
-        // >>> b = bytearray(a)
-        // >>> a[1:6:2] = []
-        // Traceback (most recent call last):
-        // File "<stdin>", line 1, in <module>
-        // ValueError: attempt to assign sequence of size 0 to extended slice of size 3
-        // >>> b[1:6:2] = []
-        // >>> b
-        // bytearray(b'\x00\x02\x04\x06\x07\x08\t')
-        //
         @Override
         public void checkIdxAndSetSlice(PySlice slice, PyObject value) {
             if (value.__len__() != 0) {
@@ -757,9 +747,14 @@
                 super.checkIdxAndSetSlice(slice, value);
             } else {
                 // Treat as deletion
-                super.checkIdxAndDelItem(slice);
+                checkIdxAndDelItem(slice);
             }
         }
+
+        @Override
+        protected void delSlice(int[] indices) {
+            delslice(indices[0], indices[1], indices[2], indices[3]);
+        }
     };
 
     /*
diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java
--- a/src/org/python/core/PyByteArray.java
+++ b/src/org/python/core/PyByteArray.java
@@ -676,53 +676,59 @@
         }
     }
 
-    /*
-     * Deletes an element from the sequence (and closes up the gap).
-     *
-     * @param index index of the element to delete.
-     */
     @Override
     protected synchronized void del(int index) {
-        // XXX Change SequenceIndexDelegate to avoid repeated calls to del(int) for extended slice
         storageDelete(index, 1);
     }
 
-    /*
-     * Deletes contiguous sub-sequence (and closes up the gap).
-     *
-     * @param start the position of the first element.
-     *
-     * @param stop one more than the position of the last element.
-     */
     @Override
     protected synchronized void delRange(int start, int stop) {
         storageDelete(start, stop - start);
     }
 
-    /**
-     * Deletes a simple or extended slice and closes up the gap(s).
-     *
-     * @param start the position of the first element.
-     * @param stop one more than the position of the last element.
-     * @param step from one element to the next
-     */
-    protected synchronized void delslice(int start, int stop, int step) {
+    @Override
+    protected synchronized void delslice(int start, int stop, int step, int n) {
+        // This will not be possible if this object has buffer exports
+        resizeCheck();
+
         if (step == 1) {
-            // Delete this[start:stop] and closing up the space
-            storageDelete(start, stop - start);
+            // Delete this[start:stop] and close up the space.
+            storageDelete(start, n);
+
+        } else if (step == -1) {
+            // Also a contiguous case, but start > stop.
+            storageDelete(stop + 1, n);
+
         } else {
-            // This is an extended slice which means we are removing isolated elements
-            int n = sliceLength(start, stop, step);
+            // This is an extended slice. We will be deleting n isolated elements.
+            int p, m;
 
-            if (n > 0) {
-                if (step > 0) {
-                    // The first element is x[start] and the last is x[start+(n-1)*step+1]
-                    storageDeleteEx(start, step, n);
-                } else {
-                    // The first element is x[start+(n-1)*step+1] and the last is x[start]
-                    storageDeleteEx(start + (n - 1) * step + 1, -step, n);
+            // We delete by copying from high to low memory, whatever the sign of step.
+            if (step > 1) {
+                // The lowest numbered element to delete is x[start]
+                p = start;
+                m = step - 1;
+            } else {
+                // The lowest numbered element to delete is x[start+(n-1)*step]]
+                p = start + (n - 1) * step;
+                m = -1 - step;
+            }
+
+            // Offset p to be a storage index.
+            p += offset;
+
+            // Copy n-1 blocks blocks of m bytes, each time skipping the byte to be deleted.
+            for (int i = 1; i < n; i++) {
+                // Skip q over the one we are deleting
+                int q = p + i;
+                // Now copy the m elements that follow.
+                for (int j = 0; j < m; j++) {
+                    storage[p++] = storage[q++];
                 }
             }
+
+            // Close up the gap. Note that for the copy, p was adjusted by the storage offset.
+            storageDelete(p - offset, n);
         }
     }
 
@@ -2654,47 +2660,4 @@
         }
     }
 
-    /**
-     * Delete <code>d</code> elements on a stride of <code>c</code> beginning at index
-     * <code>a</code> by moving together the surrounding elements. The method manipulates the
-     * <code>storage</code> array, <code>size</code> and <code>offset</code>, and will allocate a
-     * new storage array if the deletion is big enough. If the initial storage looks like this:
-     *
-     * <pre>
-     * |-                               L                                -|
-     *       |-                    s                    -|
-     * |--f--|-----a-----|---------e---------|-----b-----|----------------|
-     * </pre>
-     *
-     * then after the call the (possibly new) storage looks like this:
-     *
-     * <pre>
-     * |-                   L'                         -|
-     *      |-                s'               -|
-     * |-f'-|-----a-----|---(e-d)---|-----b-----|-------|
-     * </pre>
-     *
-     * where the regions of length <code>a</code> and <code>b=size-(a+e)</code> have been preserved
-     * and the <code>e</code> intervening elements reduced to <code>e-d</code> elements, by removing
-     * exactly the elements with indices (relative to the start of valid data) <code>a+k*c</code>
-     * for <code>k=0...d-1</code>. The effect on this <code>PyByteArray</code> is that:
-     *
-     * <pre>
-     * this.offset = f'
-     * this.size = s' = a+b
-     * </pre>
-     *
-     * The method does not implement the Python repertoire of slice indices but avoids indexing
-     * outside the <code>bytearray</code> by silently adjusting a to be within it. Negative d is
-     * treated as 0 and if d is too large, it is truncated to the array end.
-     *
-     * @param a index of hole in byte array
-     * @param c (>0) step size between the locations of elements to delete
-     * @param d number to discard (will discard x[a+k*c] for k=0...d-1)
-     */
-    private void storageDeleteEx(int a, int c, int d) {
-
-        // XXX Base this on storageReplace with the same a<b logic but piecewise copy
-        // XXX Change SequenceIndexDelegate to use (and PyList to implement) delslice()
-    }
 }
diff --git a/src/org/python/core/PySequence.java b/src/org/python/core/PySequence.java
--- a/src/org/python/core/PySequence.java
+++ b/src/org/python/core/PySequence.java
@@ -2,8 +2,8 @@
 package org.python.core;
 
 /**
- * The abstract superclass of PyObjects that implements a Sequence. Minimize the work in
- * creating such objects.
+ * The abstract superclass of PyObjects that implements a Sequence. Minimize the work in creating
+ * such objects.
  *
  * Method names are designed to make it possible for subclasses of PySequence to implement
  * java.util.List.
@@ -24,7 +24,7 @@
 
     /**
      * Construct a PySequence for the given sub-type with the default index behaviour.
-     * 
+     *
      * @param type actual (Python) type of sub-class
      */
     protected PySequence(PyType type) {
@@ -36,7 +36,7 @@
      * Construct a PySequence for the given sub-type with custom index behaviour. In practice,
      * restrictions on the construction of inner classes will mean null has to be passed and the
      * actual delegator assigned later.
-     * 
+     *
      * @param type actual (Python) type of sub-class
      * @param behaviour specific index behaviour (or null)
      */
@@ -51,7 +51,7 @@
      * PySequence in its implementation of {@link #__getitem__} It is guaranteed by PySequence that
      * when it calls <code>pyget(int)</code> the index is within the bounds of the array. Any other
      * clients must make the same guarantee.
-     * 
+     *
      * @param index index of element to return.
      * @return the element at the given position in the list.
      */
@@ -68,8 +68,8 @@
     protected abstract PyObject getslice(int start, int stop, int step);
 
     /**
-     * Returns a (concrete subclass of) PySequence that repeats the given sequence, as
-     * in the implementation of <code>__mul__</code> for strings.
+     * Returns a (concrete subclass of) PySequence that repeats the given sequence, as in the
+     * implementation of <code>__mul__</code> for strings.
      *
      * @param count the number of times to repeat the sequence.
      * @return this sequence repeated count times.
@@ -82,7 +82,7 @@
      * called by PySequence in its implementation of {@link #__setitem__} It is guaranteed by
      * PySequence that when it calls pyset(int) the index is within the bounds of the array. Any
      * other clients must make the same guarantee.
-     * 
+     *
      * @param index index of the element to set.
      * @param value the value to set this element to.
      */
@@ -91,45 +91,60 @@
     }
 
     /**
-     * Sets the given range of elements according to Python slice assignment semantics.
-     * If the step size is one, it is a simple slice and the operation is equivalent to
-     * deleting that slice, then inserting the value at that position, regarding the
-     * value as a sequence (if possible) or as a single element if it is not a sequence.
-     * If the step size is not one, but <code>start==stop</code>, it is equivalent to insertion
-     * at that point.
-     * If the step size is not one, and <code>start!=stop</code>, the slice defines a certain number
-     * of elements to be replaced, and the value must be a sequence of exactly that many
-     * elements (or convertible to such a sequence).
-     * 
+     * Sets the given range of elements according to Python slice assignment semantics. If the step
+     * size is one, it is a simple slice and the operation is equivalent to deleting that slice,
+     * then inserting the value at that position, regarding the value as a sequence (if possible) or
+     * as a single element if it is not a sequence. If the step size is not one, but
+     * <code>start==stop</code>, it is equivalent to insertion at that point. If the step size is
+     * not one, and <code>start!=stop</code>, the slice defines a certain number of elements to be
+     * replaced, and the value must be a sequence of exactly that many elements (or convertible to
+     * such a sequence).
+     *
      * @param start the position of the first element.
      * @param stop one more than the position of the last element.
      * @param step the step size.
      * @param value an object consistent with the slice assignment
      */
     protected void setslice(int start, int stop, int step, PyObject value) {
-        throw Py.TypeError(String.format("'%s' object does not support item assignment",
-                                         getType().fastGetName()));
+        throw Py.TypeError(String.format("'%s' object does not support item assignment", getType()
+                .fastGetName()));
     }
 
     /**
      * Deletes an element from the sequence (and closes up the gap).
-     * 
+     *
      * @param index index of the element to delete.
      */
     protected void del(int index) {
-        throw Py.TypeError(String.format("'%s' object does not support item deletion",
-                                         getType().fastGetName()));
+        delslice(index, index, 1, 1); // Raises TypeError (for immutable types).
     }
 
     /**
      * Deletes a contiguous sub-sequence (and closes up the gap).
-     * 
+     *
      * @param start the position of the first element.
      * @param stop one more than the position of the last element.
      */
     protected void delRange(int start, int stop) {
-        throw Py.TypeError(String.format("'%s' object does not support item deletion",
-                                         getType().fastGetName()));
+        delslice(start, stop, 1, Math.abs(stop - start)); // Raises TypeError (for immutable types).
+    }
+
+    /**
+     * Deletes a simple or extended slice and closes up the gap(s). The slice parameters
+     * <code>[start:stop:step]</code> mean what they would in Python, <i>after</i> application of
+     * the "end-relative" rules for negative numbers and <code>None</code>. The count <code>n</code>
+     * is as supplied by {@link PySlice#indicesEx(int)}. This method is unsafe in that slice
+     * parameters are assumed correct.
+     *
+     * @param start the position of the first element.
+     * @param stop beyond the position of the last element (not necessarily just beyond).
+     * @param step from one element to the next (positive or negative)
+     * @param n number of elements to delete
+     */
+    protected void delslice(int start, int stop, int step, int n) {
+        // Raises TypeError (for immutable types).
+        throw Py.TypeError(String.format("'%s' object does not support item deletion", getType()
+                .fastGetName()));
     }
 
     @Override
@@ -265,10 +280,9 @@
     /**
      * Compare the specified object/length pairs.
      *
-     * @return value >= 0 is the index where the sequences differs.
-     *         -1: reached the end of o1 without a difference
-     *         -2: reached the end of both seqeunces without a difference
-     *         -3: reached the end of o2 without a difference
+     * @return value >= 0 is the index where the sequences differs. -1: reached the end of o1
+     *         without a difference -2: reached the end of both seqeunces without a difference -3:
+     *         reached the end of o2 without a difference
      */
     protected static int cmp(PyObject o1, int ol1, PyObject o2, int ol2) {
         if (ol1 < 0) {
@@ -320,9 +334,8 @@
     }
 
     /**
-     * Adjusts <code>index</code> such that it's >= 0 and <= __len__. If
-     * <code>index</code> starts off negative, it's treated as an index from the end of
-     * the sequence going back to the start.
+     * Adjusts <code>index</code> such that it's >= 0 and <= __len__. If <code>index</code> starts
+     * off negative, it's treated as an index from the end of the sequence going back to the start.
      */
     protected int boundToSequence(int index) {
         int length = __len__();
@@ -514,7 +527,6 @@
             delRange(start, stop);
         }
 
-
         @Override
         public PyObject getItem(int idx) {
             return pyget(idx);
diff --git a/src/org/python/core/SequenceIndexDelegate.java b/src/org/python/core/SequenceIndexDelegate.java
--- a/src/org/python/core/SequenceIndexDelegate.java
+++ b/src/org/python/core/SequenceIndexDelegate.java
@@ -109,7 +109,14 @@
         }
     }
 
-    private void delSlice(int[] indices) {
+    /**
+     * Implement the deletion of a slice. This method is called by
+     * {@link #checkIdxAndDelItem(PyObject)} when the argument is a {@link PySlice}. The argument is
+     * the return from {@link PySlice#indicesEx(int)}.
+     *
+     * @param indices containing [start, stop, step, count] of the slice to delete
+     */
+    protected void delSlice(int[] indices) {
         int p = indices[0], step = indices[2], count = indices[3];
         if (step > 1) {
             /*
diff --git a/tests/java/org/python/core/BaseBytesTest.java b/tests/java/org/python/core/BaseBytesTest.java
--- a/tests/java/org/python/core/BaseBytesTest.java
+++ b/tests/java/org/python/core/BaseBytesTest.java
@@ -33,7 +33,7 @@
     // Constants for array sizes
     public static final int SMALL = 7; // Less than minimum storage size
     public static final int MEDIUM = 25; // Medium array size
-    public static final int LARGE = 10000; // Large enough for performance measurement
+    public static final int LARGE = 2000; // Large enough for performance measurement
     public static final int HUGE = 100000; // Serious performance challenge
 
     /**
@@ -55,7 +55,7 @@
 
     /**
      * Turn a String into ints, but in the Python byte range, reducing character codes mod 256.
-     * 
+     *
      * @param s the string
      * @return
      */
@@ -71,7 +71,7 @@
 
     /**
      * Generate ints at random in the range 0..255.
-     * 
+     *
      * @param random the random generator
      * @param n length of array
      * @return the array of random values
@@ -86,7 +86,7 @@
 
     /**
      * Generate ints at random in a restricted range.
-     * 
+     *
      * @param random the random generator
      * @param n length of array
      * @param lo lowest value to generate
@@ -104,7 +104,7 @@
 
     /**
      * Compare expected and result array sections at specified locations and length.
-     * 
+     *
      * @param expected reference values (may be null iff len==0)
      * @param first first value to compare in expected values
      * @param result bytearray from method under test
@@ -114,7 +114,9 @@
     static void checkInts(int[] expected, int first, BaseBytes result, int start, int len) {
         if (len > 0) {
             int end = first + len;
-            if (end > expected.length) end = expected.length;
+            if (end > expected.length) {
+                end = expected.length;
+            }
             for (int i = first, j = start; i < end; i++, j++) {
                 assertEquals("element value", expected[i], result.intAt(j));
             }
@@ -123,7 +125,7 @@
 
     /**
      * Compare expected and result array in their entirety.
-     * 
+     *
      * @param expected
      * @param result
      */
@@ -138,7 +140,7 @@
 
     /**
      * Compare expected List<PyInteger> and result array in their entirety.
-     * 
+     *
      * @param expected
      * @param result
      */
@@ -157,7 +159,7 @@
 
     /**
      * Compare expected List<PyInteger> and result object in their entirety.
-     * 
+     *
      * @param expected
      * @param result
      */
@@ -168,7 +170,7 @@
     /**
      * Turn array into Iterable<PyObject>, treating as unsigned (Python-style) bytes, and producing
      * an abusive mixture of object types.
-     * 
+     *
      * @return iterable list
      */
     public static Iterable<PyObject> iterableBytes(int[] source) {
@@ -198,7 +200,7 @@
 
     /*
      * (non-Javadoc)
-     * 
+     *
      * @see junit.framework.TestCase#setUp()
      */
     protected void setUp() throws Exception {
@@ -206,7 +208,6 @@
         random = new Random(20120310L);
     }
 
-
     /**
      * Test method for {@link org.python.core.BaseBytes#init(int)} via MyBytes constructor, and for
      * {@link org.python.core.BaseBytes#size()}.
@@ -274,17 +275,13 @@
      */
     public void testInit_PyObject() {
         // A scary set of objects
-        final PyObject[] brantub = {null,
-                                    new PyInteger(5),
-                                    new PyString("\u00A0\u00A1\u00A2\u00A3\u00A4"),
-                                    getInstance(new int[] {180, 190, 200}),
-                                    new PyXRange(1, 301, 50)};
+        final PyObject[] brantub =
+                {null, new PyInteger(5), new PyString("\u00A0\u00A1\u00A2\u00A3\u00A4"),
+                        getInstance(new int[] {180, 190, 200}), new PyXRange(1, 301, 50)};
         // The array contents we should obtain
-        final int[][] prize = { {},
-                               {0, 0, 0, 0, 0},
-                               {160, 161, 162, 163, 164},
-                               {180, 190, 200},
-                               {1, 51, 101, 151, 201, 251}};
+        final int[][] prize =
+                { {}, {0, 0, 0, 0, 0}, {160, 161, 162, 163, 164}, {180, 190, 200},
+                        {1, 51, 101, 151, 201, 251}};
         // Work down the lists
         for (int dip = 0; dip < brantub.length; dip++) {
             int[] aRef = prize[dip];
@@ -359,7 +356,7 @@
 
     /**
      * Test method for {@link BaseBytes#getslice(int, int, int)}.
-     * 
+     *
      * @see PySequence#__getslice__(PyObject, PyObject)
      */
     public void testGetslice() {
@@ -480,7 +477,7 @@
             a.setslice(start, stop, step, x);
             System.out.println(toString(a));
             fail(String.format("Exception not thrown for setslice(%d,%d,%d,%s)", start, stop, step,
-                               x));
+                    x));
         } catch (PyException pye) {
             // System.out.println(pye);
             PyObject b = pye.type;
@@ -549,7 +546,7 @@
 
         /**
          * Create a zero-length Python byte array of explicitly-specified sub-type
-         * 
+         *
          * @param type explicit Jython type
          */
         public MyBytes(PyType type) {
@@ -565,7 +562,7 @@
 
         /**
          * Create zero-filled Python byte array of specified size.
-         * 
+         *
          * @param size of byte array
          */
         public MyBytes(int size) {
@@ -574,7 +571,7 @@
 
         /**
          * Create from integer array
-         * 
+         *
          * @param value
          */
         MyBytes(int[] value) {
@@ -583,7 +580,7 @@
 
         /**
          * Create a new array filled exactly by a copy of the contents of the source byte array.
-         * 
+         *
          * @param value of the bytes
          */
         public MyBytes(BaseBytes value) {
@@ -593,7 +590,7 @@
 
         /**
          * Create a new array filled exactly by a copy of the contents of the source.
-         * 
+         *
          * @param value source of the bytes (and size)
          */
         public MyBytes(BufferProtocol value) {
@@ -604,7 +601,7 @@
         /**
          * Create a new array filled from an iterable of PyObject. The iterable must yield objects
          * convertible to Python bytes (non-negative integers less than 256 or strings of length 1).
-         * 
+         *
          * @param value of the bytes
          */
         public MyBytes(Iterable<? extends PyObject> value) {
@@ -615,7 +612,7 @@
         /**
          * Create a new array by encoding a PyString argument to bytes. If the PyString is actually
          * a PyUnicode, the encoding must be explicitly specified.
-         * 
+         *
          * @param arg primary argument from which value is taken
          * @param encoding name of optional encoding (must be a string type)
          * @param errors name of optional errors policy (must be a string type)
@@ -628,7 +625,7 @@
         /**
          * Create a new array by encoding a PyString argument to bytes. If the PyString is actually
          * a PyUnicode, the encoding must be explicitly specified.
-         * 
+         *
          * @param arg primary argument from which value is taken
          * @param encoding name of optional encoding (may be null to select the default for this
          *            installation)
@@ -658,7 +655,7 @@
          * {@link #MyBytes(PyString, String, String)}. If the PyString is actually a PyUnicode, an
          * encoding must be specified, and using this constructor will throw an exception about
          * that.
-         * 
+         *
          * @param arg primary argument from which value is taken (may be null)
          * @throws PyException in the same circumstances as bytes(arg), TypeError for non-iterable,
          *             non-integer argument type, and ValueError if iterables do not yield byte
@@ -675,7 +672,7 @@
          * just one term. It is safe because MyBytes is immutable. But it may not be wise if the
          * source object is a large array from which only a small part needs to be retained in
          * memory.
-         * 
+         *
          * @param type explicit Jython type
          * @param start index of first byte to use in source
          * @param stop 1 + index of last byte to use in source
@@ -689,7 +686,7 @@
         /**
          * Returns a PyByteArray that repeats this sequence the given number of times, as in the
          * implementation of <tt>__mul__</tt> for strings.
-         * 
+         *
          * @param count the number of times to repeat this.
          * @return this byte array repeated count times.
          */
@@ -702,7 +699,7 @@
 
         /**
          * Returns a range of elements from the sequence.
-         * 
+         *
          * @see org.python.core.PySequence#getslice(int, int, int)
          */
         @Override
@@ -727,7 +724,7 @@
 
         /**
          * Return number of elements
-         * 
+         *
          * @see org.python.core.PyObject#__len__()
          */
         @Override
@@ -776,7 +773,7 @@
 
         /**
          * Store integer array as bytes: range must be 0..255 inclusive.
-         * 
+         *
          * @param value integers to store
          */
         BufferedObject(int[] value) {
@@ -823,8 +820,9 @@
 
         // Show in image s[pos:pos+n] (as 2*n characters)
         private void append(byte[] s, int pos, int n) {
-            if (pos < 0 || pos + n > s.length)
+            if (pos < 0 || pos + n > s.length) {
                 return;
+            }
             for (int i = 0; i < n; i++) {
                 int c = 0xff & ((int)s[pos + i]);
                 if (c == 0) {
@@ -836,7 +834,7 @@
             }
         }
 
-        // Show an extent of n bytes (as 2*n charactrs)
+        // Show an extent of n bytes (as 2*n characters)
         public void padTo(int n) {
             while (n > image.length()) {
                 image.append(' ');
@@ -845,7 +843,7 @@
 
         /**
          * Write summary numbers offset [ size ] remainder
-         * 
+         *
          * @param b
          */
         public String showSummary(BaseBytes b) {
@@ -857,7 +855,7 @@
 
         /**
          * Make text image of just the buffer boundaries.
-         * 
+         *
          * @param b
          */
         public String showExtent(BaseBytes b) {
@@ -871,7 +869,7 @@
 
         /**
          * Make text image of the buffer content and boundaries.
-         * 
+         *
          * @param b
          */
         public String showContent(BaseBytes b) {
@@ -895,7 +893,7 @@
      * struct</a>. <code>buf</code> is an n-dimensional array of Object, implementing the storage of
      * some Python type, and it is required to access one element of it at an index defined by n
      * integers in sequence.
-     * 
+     *
      * @param n The number of dimensions the memory represents as a multi-dimensional array.
      * @param buf An n-dimensional array containing the value of the object
      * @param strides An array of length n giving the number of elements to skip to get to a new
@@ -904,7 +902,8 @@
      * @param indices An array of n indices indexing the element to retrieve.
      * @return
      */
-    private static Object getItem(int n, Object buf, int[] strides, int[] suboffsets, int[] indices) {
+    private static Object
+            getItem(int n, Object buf, int[] strides, int[] suboffsets, int[] indices) {
         for (int i = 0; i < n; i++) {
             Object[] p = (Object[])buf;
             buf = p[indices[i] * strides[i] + suboffsets[i]];
@@ -916,7 +915,8 @@
      * If it was an ndim-dimensional array of byte, we treat it as an (ndim-1)-dimensional array of
      * byte[] arrays. This method exemplifies getting just one byte.
      */
-    private static byte getByte(int ndim, Object buf, int[] strides, int[] suboffsets, int[] indices) {
+    private static byte
+            getByte(int ndim, Object buf, int[] strides, int[] suboffsets, int[] indices) {
         int n = ndim - 1;
         byte[] b = (byte[])getItem(n, buf, strides, suboffsets, indices);
         return b[indices[n] + suboffsets[n]];
diff --git a/tests/java/org/python/core/PyByteArrayTest.java b/tests/java/org/python/core/PyByteArrayTest.java
--- a/tests/java/org/python/core/PyByteArrayTest.java
+++ b/tests/java/org/python/core/PyByteArrayTest.java
@@ -7,7 +7,6 @@
 
 import org.python.util.PythonInterpreter;
 
-
 /**
  * JUnit tests for PyByteArray.
  */
@@ -15,6 +14,7 @@
 
     /**
      * Constructor required by JUnit.
+     *
      * @param name
      */
     public PyByteArrayTest(String name) {
@@ -137,7 +137,8 @@
      * @param y source of the E data
      * @param result the result to be tested against A+E+B
      */
-    public static void checkSlice(int na, int nd, int nb, int ne, int[] x, int[] y, BaseBytes result) {
+    public static void
+            checkSlice(int na, int nd, int nb, int ne, int[] x, int[] y, BaseBytes result) {
         // Check the size is right
         assertEquals("size", na + ne + nb, result.size());
         // Check that A is preserved
@@ -293,6 +294,7 @@
      *
      * @see org.python.core.BaseBytesTest#setUp()
      */
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
     }
@@ -305,7 +307,7 @@
     public void test__getslice__2() {
         int verbose = 0;
         // __getslice__() deals with start, stop values also relative to the end.
-        String ver = "D�rob�e au sang de nos c�urs";
+        String ver = "L'un a la pourpre de nos âmes";
         final int L = ver.length();
         int[] aRef = toInts(ver);
         BaseBytes a = getInstance(aRef);
@@ -370,11 +372,8 @@
      * @param bList reference answer
      * @param verbose 0..4 control output
      */
-    private void doTest__getslice__2(BaseBytes a,
-                                     PyObject pyStart,
-                                     PyObject pyStop,
-                                     List<PyInteger> bList,
-                                     int verbose) {
+    private void doTest__getslice__2(BaseBytes a, PyObject pyStart, PyObject pyStop,
+            List<PyInteger> bList, int verbose) {
         if (verbose >= 4) {
             System.out.printf("    __getslice__(%s,%s)\n", pyStart, pyStop);
         }
@@ -519,12 +518,8 @@
      * @param bList reference answer
      * @param verbose 0..4 control output
      */
-    private void doTest__getslice__3(BaseBytes a,
-                                     PyObject pyStart,
-                                     PyObject pyStop,
-                                     PyObject pyStep,
-                                     List<PyInteger> bList,
-                                     int verbose) {
+    private void doTest__getslice__3(BaseBytes a, PyObject pyStart, PyObject pyStop,
+            PyObject pyStep, List<PyInteger> bList, int verbose) {
         if (verbose >= 4) {
             System.out.printf("    __getslice__(%s,%s,%s)\n", pyStart, pyStop, pyStep);
         }
@@ -539,6 +534,7 @@
      * Test method for {@link PyByteArray#__setitem__(int,PyObject)}, and through it of
      * {@link PyByteArray#pyset(int,PyObject)}.
      */
+    @Override
     public void testPyset() {
         int verbose = 0;
 
@@ -629,8 +625,8 @@
                         b.setslice(na, na + nd, 1, e);
 
                         if (verbose >= 2) {
-                            boolean avAlloc = (b.storage != oldStorage)
-                                    && (bRef.length <= oldStorage.length);
+                            boolean avAlloc =
+                                    (b.storage != oldStorage) && (bRef.length <= oldStorage.length);
                             if (b.storage.length * 2 < oldStorage.length) {
                                 avAlloc = false;
                             }
@@ -664,7 +660,7 @@
                         PyByteArray e = y.getslice(0, ne, 1);
                         if (verbose >= 2) {
                             System.out.printf("setslice(start=%d, stop=%d, step=%d, e[len=%d])\n",
-                                              na, na + nd, 1, ne);
+                                    na, na + nd, 1, ne);
                             if (verbose >= 3) {
                                 System.out.println("u = " + toString(u));
                                 System.out.println("e = " + toString(e));
@@ -714,8 +710,7 @@
             }
 
             for (int stop : posStop) {
-                if (stop < start)
-                 {
+                if (stop < start) {
                     continue; // Skip backwards cases
                 }
 
@@ -732,16 +727,16 @@
                 for (int n = 0; n <= eRef.length; n++) {
                     // Generate test result and check it
                     doTest__setslice__2(uRef, pyStart, pyStop, eFull, n, eRef, start, stop,
-                                        verbose + 2);
+                            verbose + 2);
                     // Repeat same result specifying start relative to end
                     doTest__setslice__2(uRef, pyStart_L, pyStop, eFull, n, eRef, start, stop,
-                                        verbose);
+                            verbose);
                     // Repeat same result specifying stop relative to end
                     doTest__setslice__2(uRef, pyStart, pyStop_L, eFull, n, eRef, start, stop,
-                                        verbose);
+                            verbose);
                     // Repeat same result specifying start and stop relative to end
                     doTest__setslice__2(uRef, pyStart_L, pyStop_L, eFull, n, eRef, start, stop,
-                                        verbose);
+                            verbose);
                 }
             }
         }
@@ -759,15 +754,8 @@
      * @param eRef from which eFull was initialised
      * @param verbose 0..4 control output
      */
-    private void doTest__setslice__2(int[] uRef,
-                                     PyObject pyStart,
-                                     PyObject pyStop,
-                                     BaseBytes eFull,
-                                     int n,
-                                     int[] eRef,
-                                     int start,
-                                     int stop,
-                                     int verbose) {
+    private void doTest__setslice__2(int[] uRef, PyObject pyStart, PyObject pyStop,
+            BaseBytes eFull, int n, int[] eRef, int start, int stop, int verbose) {
         PyByteArray u = getInstance(uRef);
         BaseBytes e = eFull.getslice(0, n, 1);
         if (verbose >= 4) {
@@ -790,6 +778,7 @@
      * slice to replace is extended (3-argument slice and step!=0). Note that PySequence checks and
      * converts arguments first, so we need only test with valid combinations of indices.
      */
+    @Override
     public void testSetslice3() {
         int verbose = 0;
 
@@ -820,7 +809,7 @@
                         BaseBytes e = eFull.getslice(0, n, 1);
                         if (verbose >= 2) {
                             System.out.printf("setslice(start=%d, stop=%d, step=%d, e[len=%d])\n",
-                                              start, stop, step, n);
+                                    start, stop, step, n);
                             if (verbose >= 3) {
                                 System.out.println("u = " + toString(u));
                                 System.out.println("e = " + toString(e));
@@ -855,7 +844,7 @@
                         BaseBytes e = eFull.getslice(0, n, 1);
                         if (verbose >= 2) {
                             System.out.printf("setslice(start=%d, stop=%d, step=%d, e[len=%d])\n",
-                                              start, stop, step, n);
+                                    start, stop, step, n);
                             if (verbose >= 3) {
                                 System.out.println("u = " + toString(u));
                                 System.out.println("e = " + toString(e));
@@ -913,8 +902,8 @@
                         PyByteArray u = getInstance(uRef);
                         BaseBytes e = eFull.getslice(0, n, 1);
                         if (verbose >= 2) {
-                            System.out.printf("setslice(%d,%d,%d, e[len=%d])\n", start, stop, step,
-                                              n);
+                            System.out.printf("setslice(%d,%d,%d, e[len=%d])\n", //
+                                    start, stop, step, n);
                             if (verbose >= 3) {
                                 System.out.println("u = " + toString(u));
                                 System.out.println("e = " + toString(e));
@@ -951,8 +940,8 @@
                         PyByteArray u = getInstance(uRef);
                         BaseBytes e = eFull.getslice(0, n, 1);
                         if (verbose >= 2) {
-                            System.out.printf("setslice(%d,%d,%d, e[len=%d])\n", start, stop, step,
-                                              n);
+                            System.out.printf("setslice(%d,%d,%d, e[len=%d])\n", //
+                                    start, stop, step, n);
                             if (verbose >= 3) {
                                 System.out.println("u = " + toString(u));
                                 System.out.println("e = " + toString(e));
@@ -975,10 +964,10 @@
      */
     public void testSetsliceTime() {
         int verbose = 1;
-        timeSetslice(100, 200, SMALL, 2*SMALL, verbose);
-        timeSetslice(100, 200, MEDIUM, MEDIUM, verbose);
-        timeSetslice(1000, 20, LARGE, LARGE/5, verbose);
-//        timeSetslice(1000, 4, HUGE, HUGE/5, verbose);
+        timeSetslice(50, 100, SMALL, 2 * SMALL, verbose);
+        timeSetslice(50, 100, MEDIUM, MEDIUM, verbose);
+        timeSetslice(500, 20, LARGE, LARGE / 5, verbose);
+        // timeSetslice(1000, 4, HUGE, HUGE/5, verbose);
     }
 
     /**
@@ -1092,12 +1081,8 @@
      * @param verbose amount of output
      * @return elapsed time in nanoseconds for setslice operation on array of objects
      */
-    private long doTimeSetslice(PyByteArray[] u,
-                                int start,
-                                int stop,
-                                BaseBytes e,
-                                BaseBytes x,
-                                int verbose) {
+    private long doTimeSetslice(PyByteArray[] u, int start, int stop, BaseBytes e, BaseBytes x,
+            int verbose) {
 
         // The call is either to do a time trial (block of test objects) or one test of correctness
         int repeats = 1;
@@ -1147,24 +1132,9 @@
         return t;
     }
 
-//    /**
-//     * Test method for {@link org.python.core.PyByteArray#del(int)}.
-//     */
-//    public void testDel() {
-//        fail("Not yet implemented");
-//    }
-//
-//    /**
-//     * Test method for {@link org.python.core.PyByteArray#delRange(int, int)}.
-//     */
-//    public void testDelRange() {
-//        fail("Not yet implemented");
-//    }
-//
-
     /**
-     * Test method for {@link org.python.core.PyByteArray#delslice(int,int,int)}, when the
-     * slice to delete is simple (a contiguous 2-argument slice).
+     * Test method for {@link org.python.core.PyByteArray#delslice(int,int,int)}, when the slice to
+     * delete is simple (a contiguous 2-argument slice).
      */
     public void testDelslice2() {
         int verbose = 0;
@@ -1175,39 +1145,38 @@
         int[] ndList = {5, 20, 0};  // Slice to delete is small, large or zero
         int[] nbList = {4, 7, 0};   // Interesting cases: slice is at end, or not at end
 
-            for (int nd : ndList) {
-                for (int na : naList) {
-                    for (int nb : nbList) {
-                        int[] aRef = adbInts(na, nd, nb);
-                        int[] bRef = aebInts(na, 0, nb);
+        for (int nd : ndList) {
+            for (int na : naList) {
+                for (int nb : nbList) {
+                    int[] aRef = adbInts(na, nd, nb);
+                    int[] bRef = aebInts(na, 0, nb);
 
-                        PyByteArray b = getInstance(aRef);
+                    PyByteArray b = getInstance(aRef);
 
-                        byte[] oldStorage = b.storage;
+                    byte[] oldStorage = b.storage;
 
-                        if (verbose >= 2) {
-                            System.out.printf("delslice(%d,%d,%d)\n",
-                                              na, na + nd, 1);
-                            if (verbose >= 3) {
-                                System.out.println(toString(b));
-                            }
+                    if (verbose >= 2) {
+                        System.out.printf("delslice(%d,%d,%d,%d)\n", na, na + nd, 1, nd);
+                        if (verbose >= 3) {
+                            System.out.println(toString(b));
                         }
+                    }
 
-                        b.delslice(na, na + nd, 1);
+                    b.delslice(na, na + nd, 1, nd);
 
-                        if (verbose >= 2) {
-                            // Was there a reallocation?
-                            boolean avAlloc = (b.storage != oldStorage);
-                            // Justified if ...
-                            if (bRef.length * 2 <= oldStorage.length) {
-                                avAlloc = false;
-                            }
-                            System.out.println(toString(b) + (avAlloc ? " avoidable new" : ""));
+                    if (verbose >= 2) {
+                        // Was there a reallocation?
+                        boolean avAlloc = (b.storage != oldStorage);
+                        // Justified if ...
+                        if (bRef.length * 2 <= oldStorage.length) {
+                            avAlloc = false;
                         }
-                        checkInts(bRef, b);
+                        System.out.println(toString(b) + (avAlloc ? " avoidable new" : ""));
                     }
+                    checkInts(bRef, b);
                 }
             }
+        }
 
         // Deletions at a range of positions and all sizes with random data
 
@@ -1224,21 +1193,21 @@
 
         for (int na = 0; na <= AMAX; na++) {
             for (int nb : nbList2) {
-                for (int nd = 0; nd < DMAX; nd++){
-                        PyByteArray u = x.getslice(0, na + nd + nb, 1);
-                        if (verbose >= 2) {
-                            System.out.printf("delslice(start=%d, stop=%d, step=%d)\n",
-                                              na, na + nd, 1);
-                            if (verbose >= 3) {
-                                System.out.println("u = " + toString(u));
-                            }
+                for (int nd = 0; nd < DMAX; nd++) {
+                    PyByteArray u = x.getslice(0, na + nd + nb, 1);
+                    if (verbose >= 2) {
+                        System.out.printf("delslice(start=%d, stop=%d, step=%d, n=%d)\n", na, na
+                                + nd, 1, nd);
+                        if (verbose >= 3) {
+                            System.out.println("u = " + toString(u));
                         }
-                        u.delslice(na, na + nd, 1);
-                        if (verbose >= 1) {
-                            System.out.println("u'= " + toString(u));
-                        }
-                        checkSlice(na, nd, nb, 0, xInts, null, u);
                     }
+                    u.delslice(na, na + nd, 1, nd);
+                    if (verbose >= 1) {
+                        System.out.println("u'= " + toString(u));
+                    }
+                    checkSlice(na, nd, nb, 0, xInts, null, u);
+                }
             }
         }
     }
@@ -1260,8 +1229,6 @@
 
         final int[] posStart = new int[] {0, 3, 7, 16, L - 1};
         final int[] posStop = new int[] {0, 3, 7, 16, L - 6, L};
-//        final int[] posStart = new int[] {16};
-//        final int[] posStop = new int[] {L};
 
         for (int start : posStart) {
             PyObject pyStart, pyStop, pyStart_L, pyStop_L;
@@ -1275,8 +1242,7 @@
             }
 
             for (int stop : posStop) {
-                if (stop < start)
-                 {
+                if (stop < start) {
                     continue; // Skip backwards cases
                 }
 
@@ -1311,10 +1277,8 @@
      * @param pyStop
      * @param verbose 0..4 control output
      */
-    private void doTest__delslice__2(int[] uRef,
-                                     PyObject pyStart,
-                                     PyObject pyStop,
-                                     int start, int stop, int verbose) {
+    private void doTest__delslice__2(int[] uRef, PyObject pyStart, PyObject pyStop, int start,
+            int stop, int verbose) {
         PyByteArray u = getInstance(uRef);
         if (verbose >= 4) {
             System.out.printf("    __delslice__(%s,%s,1)\n", pyStart, pyStop);
@@ -1325,16 +1289,15 @@
         if (verbose >= 3) {
             System.out.println("u'= " + toString(u));
         }
-        int nd = stop-start;
-        int nb = uRef.length-stop;
+        int nd = stop - start;
+        int nb = uRef.length - stop;
         checkSlice(start, nd, nb, 0, uRef, null, u);
     }
 
-
     /**
-     * Test method for {@link org.python.core.PyByteArray#delslice(int,int,int)}, when the
-     * slice to delete is extended (3-argument slice and step!=0). Note that PySequence checks and
-     * converts arguments first, so we need only test with valid combinations of indices.
+     * Test method for {@link org.python.core.PyByteArray#delslice(int,int,int)}, when the slice to
+     * delete is extended (3-argument slice and step!=0). Note that PySequence checks and converts
+     * arguments first, so we need only test with valid combinations of indices.
      */
     public void test__delslice__3() {
         int verbose = 0;
@@ -1342,10 +1305,6 @@
         // Need interpreter
         interp = new PythonInterpreter();
 
-        // Source of assigned values.
-//        int[] eRef = randomInts(random, MEDIUM, 'A', 'H');
-//        BaseBytes eFull = new BaseBytesTest.MyBytes(eRef);
-
         // Forwards cases
 
         int[] uRef = randomInts(random, MEDIUM, 'm', 's');
@@ -1370,8 +1329,8 @@
                         // Now do the test
                         PyByteArray u = getInstance(uRef);
                         if (verbose >= 2) {
-                            System.out.printf("delslice(%d,%d,%d) (%d deletions)\n",
-                                              start, stop, step, n);
+                            System.out.printf("__delslice__(%d,%d,%d) (%d deletions)\n", start,
+                                    stop, step, n);
                             if (verbose >= 3) {
                                 System.out.println("u = " + toString(u));
                             }
@@ -1406,8 +1365,8 @@
                         // Now do the test
                         PyByteArray u = getInstance(uRef);
                         if (verbose >= 2) {
-                            System.out.printf("delslice(%d,%d,%d) (%d deletions)\n",
-                                              start, stop, step, n);
+                            System.out.printf("__delslice__(%d,%d,%d) (%d deletions)\n", start,
+                                    stop, step, n);
                             if (verbose >= 3) {
                                 System.out.println("u = " + toString(u));
                             }
@@ -1430,9 +1389,9 @@
      */
     public void testDelsliceTime3() {
         int verbose = 1;
-        timeDelslice3(100, 200, SMALL, verbose);
-        timeDelslice3(100, 200, MEDIUM, verbose);
-        timeDelslice3(10, 4, LARGE, verbose);
+        timeDelslice3(50, 100, SMALL, verbose);
+        timeDelslice3(50, 100, MEDIUM, verbose);
+        timeDelslice3(20, 4, LARGE, verbose);
         // timeDelslice3(10, 1, HUGE, verbose);
     }
 
@@ -1494,10 +1453,10 @@
 
                     if (step > 0) {
                         // Deletions available from start location to end of array
-                        n = (xRef.length - start + step-1) / step;
+                        n = (xRef.length - start + step - 1) / step;
                     } else {
                         // Deletions available from start location to beginning of array
-                        n = (start + (-step) ) / (-step);
+                        n = (start + (-step)) / (-step);
                     }
 
                     // Make objects of the arguments
@@ -1554,12 +1513,8 @@
      * @param verbose amount of output
      * @return elapsed time in nanoseconds for delslice operation on array of objects
      */
-    private long doTimeDelslice3(PyByteArray[] u,
-                                 PyObject pyStart,
-                                 PyObject pyStop,
-                                 PyObject pyStep,
-                                 BaseBytes x,
-                                 int verbose) {
+    private long doTimeDelslice3(PyByteArray[] u, PyObject pyStart, PyObject pyStop,
+            PyObject pyStep, BaseBytes x, int verbose) {
 
         // The call is either to do a time trial (block of test objects) or one test of correctness
         int repeats = 1;
@@ -1614,41 +1569,49 @@
      * with a similar signature. The idea is to override the getInstance() methods to return an
      * instance of the class actually under test in the derived test.
      */
+    @Override
     public PyByteArray getInstance(PyType type) {
         return new PyByteArray(type);
     }
 
+    @Override
     public PyByteArray getInstance() {
         return new PyByteArray();
     }
 
+    @Override
     public PyByteArray getInstance(int size) {
         return new PyByteArray(size);
     }
 
+    @Override
     public PyByteArray getInstance(int[] value) {
         return new PyByteArray(value);
     }
 
+    @Override
     public PyByteArray getInstance(BaseBytes source) {
         return new PyByteArray(source);
     }
 
+    @Override
     public PyByteArray getInstance(Iterable<? extends PyObject> source) {
         return new PyByteArray(source);
     }
 
+    @Override
     public PyByteArray getInstance(PyString arg, PyObject encoding, PyObject errors) {
         return new PyByteArray(arg, encoding, errors);
     }
 
+    @Override
     public PyByteArray getInstance(PyString arg, String encoding, String errors) {
         return new PyByteArray(arg, encoding, errors);
     }
 
+    @Override
     public PyByteArray getInstance(PyObject arg) throws PyException {
         return new PyByteArray(arg);
     }
 
-
 }

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list