Author: Remi Meier <remi.me...@gmail.com>
Branch: 
Changeset: r338:c2a9d75029be
Date: 2015-11-05 12:27 +0100
http://bitbucket.org/pypy/benchmarks/changeset/c2a9d75029be/

Log:    add lee-routing benchmark for STM

        We are 11x slower for sparseshort.txt and 2x for sparselong.txt
        using pypy with STM enabled. Find out why..

diff too long, truncating to 2000 out of 13625 lines

diff --git a/multithread/lee_routing/lee_router.py 
b/multithread/lee_routing/lee_router.py
new file mode 100755
--- /dev/null
+++ b/multithread/lee_routing/lee_router.py
@@ -0,0 +1,503 @@
+#!/usr/bin/python
+
+#
+# BSD License
+#
+# Copyright (c) 2007, The University of Manchester (UK)
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#     - Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     - Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     - Neither the name of the University of Manchester nor the names
+#       of its contributors may be used to endorse or promote products
+#       derived from this software without specific prior written
+#       permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Simple Lee's Routing Algorithm
+# Author: IW
+# Translated from Java to Python by Remi Meier
+
+
+import time, Tkinter
+import sys, math
+import threading
+
+DEBUG = True
+
+CYAN = "#00FFFF"
+MAGENTA = "#FF00FF"
+YELLOW = "#FFFF00"
+GREEN = "#00FF00"
+RED = "#FF0000"
+BLUE = "#0000FF"
+
+GRID_SIZE = 600
+EMPTY = 0
+TEMP_EMPTY = 10000
+OCC = 5120
+VIA = 6000
+BVIA = 6001
+TRACK = 8192
+MAX_WEIGHT = 1
+
+# used as loop indices to look at neighbouring cells
+NEIGHBOUR_OFFS = ((1,0), (-1,0), (0,1), (0,-1))
+
+class Grid(object):
+
+    def __init__(self, width, height, depth):
+        self.width = width
+        self.height = height
+        self.depth = depth
+        self._data = [[[0 for _ in range(depth)]
+                     for _ in range(height)]
+                     for _ in range(width)]
+        self.reset(EMPTY)
+
+    def reset(self, val):
+        for col in self._data:
+            for row in col:
+                for c in range(len(row)):
+                    row[c] = val
+
+    def occupy(self, lo_x, lo_y, up_x, up_y):
+        for x in range(lo_x, up_x + 1):
+            for y in range(lo_y, up_y + 1):
+                depth = self._data[x][y]
+                for c in range(len(depth)):
+                    depth[c] = OCC
+
+
+    def add_weights(self):
+        data = self._data
+        for i in range(MAX_WEIGHT):
+            # this loop iteratively propagates weights
+            # if for MAX_WEIGHT > 1...
+            for z in range(self.depth):
+                for x in range(1, self.width - 1):
+                    for y in range(1, self.height - 1):
+                        val = data[x][y][z]
+                        if val == OCC:
+                            # for OCC fields, we set EMPTY neighbours to
+                            # MAX_WEIGHT
+                            for dx, dy in NEIGHBOUR_OFFS:
+                                if data[x + dx][y + dy][z] == EMPTY:
+                                    data[x + dx][y + dy][z] = MAX_WEIGHT
+                        elif val != EMPTY:
+                            # for MAX_WEIGHT fields, set EMPTY neighbours to
+                            # "our value - 1" --> 0 = EMPTY if MAX_WEIGHT is 1
+                            for dx, dy in NEIGHBOUR_OFFS:
+                                if data[x + dx][y + dy][z] == EMPTY:
+                                    data[x + dx][y + dy][z] = val - 1
+
+    def __getitem__(self, args):
+        x, y, z = args
+        return self._data[x][y][z]
+
+    def __setitem__(self, args, value):
+        x, y, z = args
+        self._data[x][y][z] = value
+
+
+
+
+class WorkQueue(object):
+    def __init__(self, xx1=0, yy1=0, xx2=0, yy2=0, n=0):
+        self.next = None
+        self.x1 = xx1
+        self.y1 = yy1
+        self.x2 = xx2
+        self.y2 = yy2
+        self.nn = n
+
+    def enqueue(self, x1, y1, x2, y2, n):
+        q = WorkQueue(x1, y1, x2, y2, n)
+        q.next = self.next
+        return q
+
+    def dequeue(self):
+        q = self.next
+        self.next = self.next.next
+        return q
+
+    # def length(self):
+    #     curr = self.next
+    #     retval = 0
+    #     while curr is not None:
+    #         retval += 1
+    #         curr = curr.next
+    #     return retval
+
+    def _less(self, other):
+        return (((self.x2 - self.x1) * (self.x2 - self.x1)
+                 + (self.y2 - self.y1) * (self.y2 - self.y1))
+                > ((other.x2 - other.x1) * (other.x2 - other.x1)
+                   + (other.y2 - other.y1) * (other.y2 - other.y1)))
+
+    def _pass(self):
+        done = True
+        ent = self
+        a = ent.next
+        while a.next is not None:
+            b = a.next
+            if a._less(b):
+                ent.next = b
+                a.next = b.next
+                b.next = a
+                done = False
+            ent = a
+            a = b
+            b = b.next
+        return done
+
+    def sort(self):
+        while not self._pass():
+            pass
+
+
+
+
+class LeeThread(threading.Thread):
+
+    def __init__(self, lr):
+        threading.Thread.__init__(self)
+        self.lr = lr
+        self.wq = None
+        self.tempgrid = Grid(GRID_SIZE, GRID_SIZE, 2)
+        self.hardware = "somehostname"
+
+    def run(self):
+        while True:
+            self.wq = self.lr.get_next_track()
+            #
+            if self.wq is None:
+                print "finished"
+                return
+            #
+            self.lr.lay_next_track(self.wq, self.tempgrid)
+
+
+
+
+class LeeRouter(object):
+
+    def __init__(self, file):
+        self.grid = Grid(GRID_SIZE, GRID_SIZE, 2)
+        self.work = WorkQueue()
+        self.net_no = 0
+        self._parse_data_file(file)
+        self.grid.add_weights()
+        self.work.sort()
+        self.queue_lock = threading.Lock()
+        self.grid_lock = threading.Lock()
+        self.view = Viewer()
+
+    def _parse_data_file(self, file_name):
+        with open(file_name, 'r') as file:
+            for line in file:
+                line = line.strip()
+                line = line.split()
+                c, params = line[0], map(int, line[1:])
+                if c == 'E':
+                    break # end of file
+                if c == 'C':
+                    # chip bounding box
+                    x0, y0, x1, y1 = params
+                    self.grid.occupy(x0, y0, x1, y1)
+                if c == 'P':
+                    # pad
+                    x0, y0 = params
+                    self.grid.occupy(x0, y0, x0, y0)
+                if c == 'J':
+                    # join connection pts
+                    x0, y0, x1, y1 = params
+                    self.net_no += 1
+                    self.work.next = self.work.enqueue(x0, y0, x1, y1, 
self.net_no)
+
+    def get_next_track(self):
+        with self.queue_lock:
+            if self.work.next is not None:
+                return self.work.dequeue()
+        return None
+
+    def lay_next_track(self, wq, tempgrid):
+        # start transaction
+        with self.grid_lock:
+            done = self._connect(wq.x1, wq.y1, wq.x2, wq.y2,
+                                wq.nn, tempgrid, self.grid)
+        return done # end transaction
+
+    def create_thread(self):
+        return LeeThread(self)
+
+    def _expand_from_to(self, x, y, x_goal, y_goal, num,
+                     tempgrid, grid):
+        # this method should use Lee's expansion algorithm from
+       # coordinate (x,y) to (x_goal, y_goal) for the num iterations
+       # it should return true if the goal is found and false if it is not
+       # reached within the number of iterations allowed.
+        #
+        # g[x_goal][y_goal][0] = EMPTY; // set goal as empty
+       # g[x_goal][y_goal][1] = EMPTY; // set goal as empty
+        front = []
+        tmp_front = []
+        tempgrid[x, y, 0] = 1
+        tempgrid[x, y, 1] = 1
+        #
+        front.append((x, y, 0, 0)) # (x y z dw)
+        front.append((x, y, 1, 0)) # we can start from either side
+        #
+        reached0, reached1 = False, False
+        while front:
+            while front:
+                fx, fy, fz, fdw = front.pop(0)
+                #
+                if fdw > 0:
+                    tmp_front.append((fx, fy, fz, fdw - 1))
+                else:
+                    for dx, dy in NEIGHBOUR_OFFS:
+                        fdx, fdy = fx + dx, fy + dy
+
+                        weight = grid[fdx, fdy, fz] + 1
+                        prev_val = tempgrid[fdx, fdy, fz]
+                        reached = (fdx == x_goal) and (fdy == y_goal)
+                        if reached or (
+                                prev_val > tempgrid[fx, fy, fz] + weight and 
weight < OCC):
+                            # check that a point is actually within the bounds 
of grid array:
+                            if 0 < fdx < GRID_SIZE - 1 and 0 < fdy < GRID_SIZE 
- 1:
+                                tempgrid[fdx, fdy, fz] = tempgrid[fx, fy, fz] 
+ weight
+                                if not reached:
+                                    tmp_front.append((fdx, fdy, fz, 0))
+                    #
+                    not_fz = 1 - fz
+                    weight = grid[fx, fy, not_fz] + 1
+                    if tempgrid[fx, fy, not_fz] > tempgrid[fx, fy, fz] and 
weight < OCC:
+                        tempgrid[fx, fy, not_fz] = tempgrid[fx, fy, fz]
+                        tmp_front.append((fx, fy, not_fz, 0))
+                    #
+                    # must check if found goal, if so, return True
+                    reached0 = tempgrid[x_goal, y_goal, 0] != TEMP_EMPTY
+                    reached1 = tempgrid[x_goal, y_goal, 1] != TEMP_EMPTY
+                    if reached0 and reached1: # both
+                        return True # (x_goal, y_goal) can be found in time
+            #
+            front, tmp_front = tmp_front, front
+        return False
+
+    @staticmethod
+    def _path_from_other_side(tempgrid, x, y, z):
+        zo = 1 - z # other side
+        sqval = tempgrid[x, y, zo]
+        if sqval in (VIA, BVIA):
+            return False
+        #
+        if tempgrid[x, y, zo] <= tempgrid[x, y, z]:
+            return (tempgrid[x-1, y, zo] < sqval or tempgrid[x+1, y, zo] < 
sqval
+                    or tempgrid[x, y-1, zo] < sqval or tempgrid[x, y+1, zo] < 
sqval)
+        return False
+
+    @staticmethod
+    def _tlength(x1, y1, x2, y2):
+        sq = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)
+       return math.sqrt(sq);
+
+    def _backtrack_from(self, x_goal, y_goal, x_start, y_start,
+                      track_no, tempgrid, grid):
+        # this method should backtrack from the goal position (x_goal, y_goal)
+       # back to the starting position (x_start, y_start) filling in the
+       # grid array g with the specified track number track_no ( + TRACK).
+       # ***
+       # CurrentPos = Goal
+       # Loop
+       # Find dir to start back from current position
+       # Loop
+       # Keep going in current dir and Fill in track (update currentPos)
+       # Until box number increases in this current dir
+       # Until back at starting point
+       # ***
+        distsofar = 0
+        if abs(x_goal - x_start) > abs(y_goal - y_start):
+            z_goal = 0
+        else:
+            z_goal = 1
+        #
+        if tempgrid[x_goal, y_goal, z_goal] == TEMP_EMPTY:
+            z_goal = 1 - z_goal
+        #
+        # arrays used for looking NSEW:
+        DX = (( -1, 1, 0, 0 ),
+              ( 0, 0, -1, 1 ))
+        DY = (( 0, 0, -1, 1 ),
+              ( -1, 1, 0, 0 ))
+        #
+        temp_y, temp_x, temp_z = y_goal, x_goal, z_goal
+        while (temp_x != x_start) or (temp_y != y_start): # PDL: until back
+            # at starting point
+            advanced = False
+            min_dir = 0
+            min_square = 100000
+            for d in range(4): # PDL: find dir to start back from
+                # current position
+                temp_dx, temp_dy = temp_x + DX[temp_z][d], temp_y + 
DY[temp_z][d]
+                if (tempgrid[temp_dx, temp_dy, temp_z] < tempgrid[temp_x, 
temp_y, temp_z]
+                    and tempgrid[temp_dx, temp_dy, temp_z] != TEMP_EMPTY):
+                    if tempgrid[temp_dx, temp_dy, temp_z] < min_square:
+                        min_square = tempgrid[temp_dx, temp_dy, temp_z]
+                        min_dir = d
+                        advanced = True
+            if advanced:
+                distsofar += 1
+            #
+            if (self._path_from_other_side(tempgrid, temp_x, temp_y, temp_z)
+                # not preferred dir for this layer
+                and ((min_dir > 1 and distsofar > 15
+                      and self._tlength(temp_x, temp_y, x_start, y_start) > 15)
+                     or (not advanced and
+                         grid[temp_x, temp_y, temp_z] not in (VIA, BVIA)
+                     ))):
+                t_z = 1 - temp_z
+                viat = VIA if advanced else BVIA # BVIA is nowhere else to go
+                # mark via
+                tempgrid[temp_x, temp_y, temp_z] = viat
+                grid[temp_x, temp_y, temp_z] = viat
+                # go to the other side:
+                temp_z = t_z
+                tempgrid[temp_x, temp_y, temp_z] = viat
+                grid[temp_x, temp_y, temp_z] = viat
+                distsofar = 0
+            else:
+                if grid[temp_x, temp_y, temp_z] < OCC:
+                   # PDL: fill in track unless connection point
+                   grid[temp_x, temp_y, temp_z] = TRACK
+                # PDL: updating current position
+                temp_x = temp_x + DX[temp_z][min_dir];
+               temp_y = temp_y + DY[temp_z][min_dir];
+
+    def _connect(self, xs, ys, xg, yg, net_no, tempgrid, grid):
+        # calls expand_from and backtrack_from to create connection
+       # This is the only real change needed to make the program
+       # transactional.
+       # Instead of using the grid 'in place' to do the expansion, we take a
+       # copy but the backtrack writes to the original grid.
+       # This is not a correctness issue. The transactions would still
+       # complete eventually without it.
+       # However the expansion writes are only temporary and do not logically
+       # conflict.
+       # There is a question as to whether a copy is really necessary as a
+       # transaction will anyway create
+       # its own copy. if we were then to distinguish between writes not to be
+       # committed (expansion) and
+       # those to be committed (backtrack), we would not need an explicit
+       # copy.
+       # Taking the copy is not really a computational(time) overhead because
+       # it avoids the grid 'reset' phase
+       # needed if we do the expansion in place.
+        tempgrid.reset(TEMP_EMPTY)
+        # call the expansion method to return found/not found boolean
+        found = self._expand_from_to(xs, ys, xg, yg, GRID_SIZE * 5, tempgrid, 
grid)
+        if found:
+            self._backtrack_from(xg, yg, xs, ys, net_no, tempgrid, grid)
+        return found
+
+    def disp_grid(self, z):
+        laycol = (MAGENTA, GREEN)[z]
+        for y in reversed(range(GRID_SIZE)): #WTF
+            for x in range(GRID_SIZE):
+                gg = self.grid[x, y, z]
+                if gg == OCC:
+                    self.view.point(x, y, CYAN)
+                elif gg == VIA:
+                    self.view.point(x, y, YELLOW)
+                elif gg == BVIA:
+                    self.view.point(x, y, RED)
+                elif gg == TRACK:
+                    self.view.point(x, y, laycol)
+
+
+
+def main(args):
+    if len(args) != 2:
+        print "Params: [numthreads] [input-file]"
+        sys.exit(-1)
+    #
+    num_threads = int(args[0])
+    filename = args[1]
+    lr = LeeRouter(filename)
+    #
+    # setup the benchmark
+    start_time = 0
+    current_time = 0
+    #
+    thread = [lr.create_thread() for _ in range(num_threads)]
+    start_time = time.time()
+    for t in thread:
+        t.start()
+    current_time = time.time()
+    for t in thread:
+        t.join()
+    #
+    elapsed_time = current_time - start_time
+    print "Numthreads:", num_threads
+    print "ElapsedTime:", elapsed_time, "s"
+    report(start_time)
+    if DEBUG:
+        lr.disp_grid(0)
+        lr.disp_grid(1)
+        lr.view.show()
+
+
+
+def report(start_time):
+    stop_time = time.time()
+    elapsed = stop_time - start_time
+    print "Elapsed time:", elapsed, "s"
+    print "-------------------------"
+
+
+
+class Viewer(object):
+    def __init__(self):
+        self.points = []
+
+    def point(self, x, y, col):
+        self.points.append((x, y, col))
+
+    def show(self, width=GRID_SIZE, height=GRID_SIZE):
+        master = Tkinter.Tk()
+        c = Tkinter.Canvas(master, width=width, height=height,
+                           background="black")
+        c.pack()
+        img = Tkinter.PhotoImage(width=width, height=height)
+        c.create_image((width/2, height/2), image=img,
+                       state="normal")
+        # draw
+        for (x, y, col) in self.points:
+            img.put(col, (x, y))
+            #c.create_oval(x-1, y-1, x+1, y+1, fill=col, width=0)
+        Tkinter.mainloop()
+
+
+
+if __name__ == '__main__':
+    main(sys.argv[1:])
diff --git a/multithread/lee_routing/mainboard.txt 
b/multithread/lee_routing/mainboard.txt
new file mode 100644
--- /dev/null
+++ b/multithread/lee_routing/mainboard.txt
@@ -0,0 +1,4653 @@
+P 306 476
+P 306 480
+P 306 484
+P 306 488
+P 306 492
+P 306 496
+P 306 500
+P 306 504
+P 306 508
+P 306 512
+P 306 516
+P 306 520
+P 306 524
+P 306 528
+P 306 532
+P 306 536
+P 306 540
+P 306 544
+P 306 548
+P 306 552
+P 282 552
+P 282 548
+P 282 544
+P 282 540
+P 282 536
+P 282 532
+P 282 528
+P 282 524
+P 282 520
+P 282 516
+P 282 512
+P 282 508
+P 282 504
+P 282 500
+P 282 496
+P 282 492
+P 282 488
+P 282 484
+P 282 480
+P 282 476
+P 366 526
+P 366 530
+P 366 534
+P 366 538
+P 366 542
+P 366 546
+P 366 550
+P 366 554
+P 366 558
+P 366 562
+P 366 566
+P 366 570
+P 354 570
+P 354 566
+P 354 562
+P 354 558
+P 354 554
+P 354 550
+P 354 546
+P 354 542
+P 354 538
+P 354 534
+P 354 530
+P 354 526
+P 394 526
+P 394 530
+P 394 534
+P 394 538
+P 394 542
+P 394 546
+P 394 550
+P 394 554
+P 394 558
+P 394 562
+P 394 566
+P 394 570
+P 382 570
+P 382 566
+P 382 562
+P 382 558
+P 382 554
+P 382 550
+P 382 546
+P 382 542
+P 382 538
+P 382 534
+P 382 530
+P 382 526
+P 422 526
+P 422 530
+P 422 534
+P 422 538
+P 422 542
+P 422 546
+P 422 550
+P 422 554
+P 422 558
+P 422 562
+P 422 566
+P 422 570
+P 410 570
+P 410 566
+P 410 562
+P 410 558
+P 410 554
+P 410 550
+P 410 546
+P 410 542
+P 410 538
+P 410 534
+P 410 530
+P 410 526
+P 450 526
+P 450 530
+P 450 534
+P 450 538
+P 450 542
+P 450 546
+P 450 550
+P 450 554
+P 450 558
+P 450 562
+P 450 566
+P 450 570
+P 438 570
+P 438 566
+P 438 562
+P 438 558
+P 438 554
+P 438 550
+P 438 546
+P 438 542
+P 438 538
+P 438 534
+P 438 530
+P 438 526
+P 478 526
+P 478 530
+P 478 534
+P 478 538
+P 478 542
+P 478 546
+P 478 550
+P 478 554
+P 478 558
+P 478 562
+P 478 566
+P 478 570
+P 466 570
+P 466 566
+P 466 562
+P 466 558
+P 466 554
+P 466 550
+P 466 546
+P 466 542
+P 466 538
+P 466 534
+P 466 530
+P 466 526
+P 506 526
+P 506 530
+P 506 534
+P 506 538
+P 506 542
+P 506 546
+P 506 550
+P 506 554
+P 506 558
+P 506 562
+P 506 566
+P 506 570
+P 494 570
+P 494 566
+P 494 562
+P 494 558
+P 494 554
+P 494 550
+P 494 546
+P 494 542
+P 494 538
+P 494 534
+P 494 530
+P 494 526
+P 534 526
+P 534 530
+P 534 534
+P 534 538
+P 534 542
+P 534 546
+P 534 550
+P 534 554
+P 534 558
+P 534 562
+P 534 566
+P 534 570
+P 522 570
+P 522 566
+P 522 562
+P 522 558
+P 522 554
+P 522 550
+P 522 546
+P 522 542
+P 522 538
+P 522 534
+P 522 530
+P 522 526
+P 562 526
+P 562 530
+P 562 534
+P 562 538
+P 562 542
+P 562 546
+P 562 550
+P 562 554
+P 562 558
+P 562 562
+P 562 566
+P 562 570
+P 550 570
+P 550 566
+P 550 562
+P 550 558
+P 550 554
+P 550 550
+P 550 546
+P 550 542
+P 550 538
+P 550 534
+P 550 530
+P 550 526
+P 366 444
+P 366 448
+P 366 452
+P 366 456
+P 366 460
+P 366 464
+P 366 468
+P 366 472
+P 366 476
+P 366 480
+P 366 484
+P 366 488
+P 354 488
+P 354 484
+P 354 480
+P 354 476
+P 354 472
+P 354 468
+P 354 464
+P 354 460
+P 354 456
+P 354 452
+P 354 448
+P 354 444
+P 394 444
+P 394 448
+P 394 452
+P 394 456
+P 394 460
+P 394 464
+P 394 468
+P 394 472
+P 394 476
+P 394 480
+P 394 484
+P 394 488
+P 382 488
+P 382 484
+P 382 480
+P 382 476
+P 382 472
+P 382 468
+P 382 464
+P 382 460
+P 382 456
+P 382 452
+P 382 448
+P 382 444
+P 422 444
+P 422 448
+P 422 452
+P 422 456
+P 422 460
+P 422 464
+P 422 468
+P 422 472
+P 422 476
+P 422 480
+P 422 484
+P 422 488
+P 410 488
+P 410 484
+P 410 480
+P 410 476
+P 410 472
+P 410 468
+P 410 464
+P 410 460
+P 410 456
+P 410 452
+P 410 448
+P 410 444
+P 450 444
+P 450 448
+P 450 452
+P 450 456
+P 450 460
+P 450 464
+P 450 468
+P 450 472
+P 450 476
+P 450 480
+P 450 484
+P 450 488
+P 438 488
+P 438 484
+P 438 480
+P 438 476
+P 438 472
+P 438 468
+P 438 464
+P 438 460
+P 438 456
+P 438 452
+P 438 448
+P 438 444
+P 478 444
+P 478 448
+P 478 452
+P 478 456
+P 478 460
+P 478 464
+P 478 468
+P 478 472
+P 478 476
+P 478 480
+P 478 484
+P 478 488
+P 466 488
+P 466 484
+P 466 480
+P 466 476
+P 466 472
+P 466 468
+P 466 464
+P 466 460
+P 466 456
+P 466 452
+P 466 448
+P 466 444
+P 506 444
+P 506 448
+P 506 452
+P 506 456
+P 506 460
+P 506 464
+P 506 468
+P 506 472
+P 506 476
+P 506 480
+P 506 484
+P 506 488
+P 494 488
+P 494 484
+P 494 480
+P 494 476
+P 494 472
+P 494 468
+P 494 464
+P 494 460
+P 494 456
+P 494 452
+P 494 448
+P 494 444
+P 534 444
+P 534 448
+P 534 452
+P 534 456
+P 534 460
+P 534 464
+P 534 468
+P 534 472
+P 534 476
+P 534 480
+P 534 484
+P 534 488
+P 522 488
+P 522 484
+P 522 480
+P 522 476
+P 522 472
+P 522 468
+P 522 464
+P 522 460
+P 522 456
+P 522 452
+P 522 448
+P 522 444
+P 562 444
+P 562 448
+P 562 452
+P 562 456
+P 562 460
+P 562 464
+P 562 468
+P 562 472
+P 562 476
+P 562 480
+P 562 484
+P 562 488
+P 550 488
+P 550 484
+P 550 480
+P 550 476
+P 550 472
+P 550 468
+P 550 464
+P 550 460
+P 550 456
+P 550 452
+P 550 448
+P 550 444
+P 378 242
+P 378 246
+P 378 250
+P 378 254
+P 378 258
+P 378 262
+P 378 266
+P 378 270
+P 378 274
+P 378 278
+P 378 282
+P 378 286
+P 378 290
+P 378 294
+P 354 294
+P 354 290
+P 354 286
+P 354 282
+P 354 278
+P 354 274
+P 354 270
+P 354 266
+P 354 262
+P 354 258
+P 354 254
+P 354 250
+P 354 246
+P 354 242
+P 406 226
+P 406 230
+P 406 234
+P 406 238
+P 406 242
+P 406 246
+P 406 250
+P 406 254
+P 406 258
+P 406 262
+P 394 262
+P 394 258
+P 394 254
+P 394 250
+P 394 246
+P 394 242
+P 394 238
+P 394 234
+P 394 230
+P 394 226
+P 406 286
+P 406 290
+P 406 294
+P 406 298
+P 406 302
+P 406 306
+P 406 310
+P 406 314
+P 406 318
+P 406 322
+P 394 322
+P 394 318
+P 394 314
+P 394 310
+P 394 306
+P 394 302
+P 394 298
+P 394 294
+P 394 290
+P 394 286
+P 280 40
+P 280 44
+P 280 48
+P 280 52
+P 280 56
+P 280 60
+P 280 64
+P 280 68
+P 280 72
+P 280 76
+P 268 76
+P 268 72
+P 268 68
+P 268 64
+P 268 60
+P 268 56
+P 268 52
+P 268 48
+P 268 44
+P 268 40
+P 336 534
+P 336 538
+P 336 542
+P 336 546
+P 336 550
+P 336 554
+P 336 558
+P 336 562
+P 336 566
+P 336 570
+P 324 570
+P 324 566
+P 324 562
+P 324 558
+P 324 554
+P 324 550
+P 324 546
+P 324 542
+P 324 538
+P 324 534
+P 336 466
+P 336 470
+P 336 474
+P 336 478
+P 336 482
+P 336 486
+P 336 490
+P 336 494
+P 336 498
+P 336 502
+P 324 502
+P 324 498
+P 324 494
+P 324 490
+P 324 486
+P 324 482
+P 324 478
+P 324 474
+P 324 470
+P 324 466
+P 434 226
+P 434 230
+P 434 234
+P 434 238
+P 434 242
+P 434 246
+P 434 250
+P 434 254
+P 434 258
+P 434 262
+P 422 262
+P 422 258
+P 422 254
+P 422 250
+P 422 246
+P 422 242
+P 422 238
+P 422 234
+P 422 230
+P 422 226
+P 436 286
+P 436 290
+P 436 294
+P 436 298
+P 436 302
+P 436 306
+P 436 310
+P 436 314
+P 436 318
+P 436 322
+P 424 322
+P 424 318
+P 424 314
+P 424 310
+P 424 306
+P 424 302
+P 424 298
+P 424 294
+P 424 290
+P 424 286
+P 130 432
+P 134 432
+P 138 432
+P 142 432
+P 146 432
+P 150 432
+P 154 432
+P 158 432
+P 162 432
+P 166 432
+P 166 444
+P 162 444
+P 158 444
+P 154 444
+P 150 444
+P 146 444
+P 142 444
+P 138 444
+P 134 444
+P 130 444
+P 214 540
+P 214 544
+P 214 548
+P 214 552
+P 214 556
+P 214 560
+P 214 564
+P 214 568
+P 214 572
+P 214 576
+P 202 576
+P 202 572
+P 202 568
+P 202 564
+P 202 560
+P 202 556
+P 202 552
+P 202 548
+P 202 544
+P 202 540
+P 182 540
+P 182 544
+P 182 548
+P 182 552
+P 182 556
+P 182 560
+P 182 564
+P 182 568
+P 182 572
+P 182 576
+P 170 576
+P 170 572
+P 170 568
+P 170 564
+P 170 560
+P 170 556
+P 170 552
+P 170 548
+P 170 544
+P 170 540
+P 214 468
+P 214 472
+P 214 476
+P 214 480
+P 214 484
+P 214 488
+P 214 492
+P 214 496
+P 214 500
+P 214 504
+P 214 508
+P 214 512
+P 202 512
+P 202 508
+P 202 504
+P 202 500
+P 202 496
+P 202 492
+P 202 488
+P 202 484
+P 202 480
+P 202 476
+P 202 472
+P 202 468
+P 248 468
+P 248 472
+P 248 476
+P 248 480
+P 248 484
+P 248 488
+P 248 492
+P 248 496
+P 248 500
+P 248 504
+P 236 504
+P 236 500
+P 236 496
+P 236 492
+P 236 488
+P 236 484
+P 236 480
+P 236 476
+P 236 472
+P 236 468
+P 186 468
+P 186 472
+P 186 476
+P 186 480
+P 186 484
+P 186 488
+P 186 492
+P 186 496
+P 186 500
+P 186 504
+P 186 508
+P 186 512
+P 174 512
+P 174 508
+P 174 504
+P 174 500
+P 174 496
+P 174 492
+P 174 488
+P 174 484
+P 174 480
+P 174 476
+P 174 472
+P 174 468
+P 110 540
+P 110 544
+P 110 548
+P 110 552
+P 110 556
+P 110 560
+P 110 564
+P 98 564
+P 98 560
+P 98 556
+P 98 552
+P 98 548
+P 98 544
+P 98 540
+P 46 540
+P 46 544
+P 46 548
+P 46 552
+P 46 556
+P 46 560
+P 46 564
+P 34 564
+P 34 560
+P 34 556
+P 34 552
+P 34 548
+P 34 544
+P 34 540
+P 306 460
+P 286 460
+P 248 540
+P 248 544
+P 248 548
+P 248 552
+P 248 556
+P 248 560
+P 248 564
+P 248 568
+P 248 572
+P 248 576
+P 236 576
+P 236 572
+P 236 568
+P 236 564
+P 236 560
+P 236 556
+P 236 552
+P 236 548
+P 236 544
+P 236 540
+P 336 450
+P 332 450
+P 328 450
+P 324 450
+P 320 450
+P 316 450
+P 312 450
+P 308 450
+P 448 422
+P 444 422
+P 440 422
+P 436 422
+P 432 422
+P 428 422
+P 424 422
+P 420 422
+P 420 410
+P 424 410
+P 428 410
+P 432 410
+P 436 410
+P 440 410
+P 444 410
+P 448 410
+P 254 40
+P 254 44
+P 254 48
+P 254 52
+P 254 56
+P 254 60
+P 254 64
+P 254 68
+P 254 72
+P 254 76
+P 242 76
+P 242 72
+P 242 68
+P 242 64
+P 242 60
+P 242 56
+P 242 52
+P 242 48
+P 242 44
+P 242 40
+P 172 244
+P 172 248
+P 172 252
+P 172 256
+P 172 260
+P 172 264
+P 172 268
+P 172 272
+P 172 276
+P 172 280
+P 172 284
+P 172 288
+P 160 288
+P 160 284
+P 160 280
+P 160 276
+P 160 272
+P 160 268
+P 160 264
+P 160 260
+P 160 256
+P 160 252
+P 160 248
+P 160 244
+P 172 192
+P 172 196
+P 172 200
+P 172 204
+P 172 208
+P 172 212
+P 172 216
+P 172 220
+P 172 224
+P 172 228
+P 172 232
+P 172 236
+P 160 236
+P 160 232
+P 160 228
+P 160 224
+P 160 220
+P 160 216
+P 160 212
+P 160 208
+P 160 204
+P 160 200
+P 160 196
+P 160 192
+P 172 140
+P 172 144
+P 172 148
+P 172 152
+P 172 156
+P 172 160
+P 172 164
+P 172 168
+P 172 172
+P 172 176
+P 172 180
+P 172 184
+P 160 184
+P 160 180
+P 160 176
+P 160 172
+P 160 168
+P 160 164
+P 160 160
+P 160 156
+P 160 152
+P 160 148
+P 160 144
+P 160 140
+P 172 88
+P 172 92
+P 172 96
+P 172 100
+P 172 104
+P 172 108
+P 172 112
+P 172 116
+P 172 120
+P 172 124
+P 172 128
+P 172 132
+P 160 132
+P 160 128
+P 160 124
+P 160 120
+P 160 116
+P 160 112
+P 160 108
+P 160 104
+P 160 100
+P 160 96
+P 160 92
+P 160 88
+P 172 36
+P 172 40
+P 172 44
+P 172 48
+P 172 52
+P 172 56
+P 172 60
+P 172 64
+P 172 68
+P 172 72
+P 172 76
+P 172 80
+P 160 80
+P 160 76
+P 160 72
+P 160 68
+P 160 64
+P 160 60
+P 160 56
+P 160 52
+P 160 48
+P 160 44
+P 160 40
+P 160 36
+P 110 256
+P 110 260
+P 110 264
+P 110 268
+P 110 272
+P 110 276
+P 110 280
+P 110 284
+P 110 288
+P 110 292
+P 98 292
+P 98 288
+P 98 284
+P 98 280
+P 98 276
+P 98 272
+P 98 268
+P 98 264
+P 98 260
+P 98 256
+P 128 204
+P 128 208
+P 128 212
+P 128 216
+P 128 220
+P 128 224
+P 128 228
+P 128 232
+P 128 236
+P 128 240
+P 116 240
+P 116 236
+P 116 232
+P 116 228
+P 116 224
+P 116 220
+P 116 216
+P 116 212
+P 116 208
+P 116 204
+P 138 152
+P 138 156
+P 138 160
+P 138 164
+P 138 168
+P 138 172
+P 138 176
+P 138 180
+P 138 184
+P 138 188
+P 126 188
+P 126 184
+P 126 180
+P 126 176
+P 126 172
+P 126 168
+P 126 164
+P 126 160
+P 126 156
+P 126 152
+P 148 100
+P 148 104
+P 148 108
+P 148 112
+P 148 116
+P 148 120
+P 148 124
+P 148 128
+P 148 132
+P 148 136
+P 136 136
+P 136 132
+P 136 128
+P 136 124
+P 136 120
+P 136 116
+P 136 112
+P 136 108
+P 136 104
+P 136 100
+P 148 48
+P 148 52
+P 148 56
+P 148 60
+P 148 64
+P 148 68
+P 148 72
+P 148 76
+P 148 80
+P 148 84
+P 136 84
+P 136 80
+P 136 76
+P 136 72
+P 136 68
+P 136 64
+P 136 60
+P 136 56
+P 136 52
+P 136 48
+P 68 86
+P 68 90
+P 68 94
+P 68 98
+P 68 102
+P 68 106
+P 68 110
+P 68 114
+P 68 118
+P 68 122
+P 68 126
+P 68 130
+P 56 130
+P 56 126
+P 56 122
+P 56 118
+P 56 114
+P 56 110
+P 56 106
+P 56 102
+P 56 98
+P 56 94
+P 56 90
+P 56 86
+P 84 196
+P 84 200
+P 84 204
+P 84 208
+P 84 212
+P 84 216
+P 84 220
+P 84 224
+P 84 228
+P 84 232
+P 84 236
+P 84 240
+P 72 240
+P 72 236
+P 72 232
+P 72 228
+P 72 224
+P 72 220
+P 72 216
+P 72 212
+P 72 208
+P 72 204
+P 72 200
+P 72 196
+P 72 140
+P 72 144
+P 72 148
+P 72 152
+P 72 156
+P 72 160
+P 72 164
+P 72 168
+P 72 172
+P 72 176
+P 72 180
+P 72 184
+P 60 184
+P 60 180
+P 60 176
+P 60 172
+P 60 168
+P 60 164
+P 60 160
+P 60 156
+P 60 152
+P 60 148
+P 60 144
+P 60 140
+P 84 252
+P 84 256
+P 84 260
+P 84 264
+P 84 268
+P 84 272
+P 84 276
+P 84 280
+P 84 284
+P 84 288
+P 84 292
+P 84 296
+P 72 296
+P 72 292
+P 72 288
+P 72 284
+P 72 280
+P 72 276
+P 72 272
+P 72 268
+P 72 264
+P 72 260
+P 72 256
+P 72 252
+P 28 86
+P 28 90
+P 28 94
+P 28 98
+P 28 102
+P 28 106
+P 28 110
+P 28 114
+P 28 118
+P 28 122
+P 28 126
+P 28 130
+P 16 130
+P 16 126
+P 16 122
+P 16 118
+P 16 114
+P 16 110
+P 16 106
+P 16 102
+P 16 98
+P 16 94
+P 16 90
+P 16 86
+P 40 152
+P 40 156
+P 40 160
+P 40 164
+P 40 168
+P 40 172
+P 40 176
+P 40 180
+P 40 184
+P 40 188
+P 40 192
+P 40 196
+P 28 196
+P 28 192
+P 28 188
+P 28 184
+P 28 180
+P 28 176
+P 28 172
+P 28 168
+P 28 164
+P 28 160
+P 28 156
+P 28 152
+P 52 214
+P 52 218
+P 52 222
+P 52 226
+P 52 230
+P 52 234
+P 52 238
+P 52 242
+P 52 246
+P 52 250
+P 52 254
+P 52 258
+P 40 258
+P 40 254
+P 40 250
+P 40 246
+P 40 242
+P 40 238
+P 40 234
+P 40 230
+P 40 226
+P 40 222
+P 40 218
+P 40 214
+P 46 466
+P 46 470
+P 46 474
+P 46 478
+P 46 482
+P 46 486
+P 46 490
+P 46 494
+P 46 498
+P 46 502
+P 46 506
+P 46 510
+P 34 510
+P 34 506
+P 34 502
+P 34 498
+P 34 494
+P 34 490
+P 34 486
+P 34 482
+P 34 478
+P 34 474
+P 34 470
+P 34 466
+P 24 466
+P 24 470
+P 24 474
+P 24 478
+P 24 482
+P 24 486
+P 24 490
+P 24 494
+P 24 498
+P 24 502
+P 24 506
+P 24 510
+P 12 510
+P 12 506
+P 12 502
+P 12 498
+P 12 494
+P 12 490
+P 12 486
+P 12 482
+P 12 478
+P 12 474
+P 12 470
+P 12 466
+P 106 304
+P 106 308
+P 106 312
+P 106 316
+P 106 320
+P 106 324
+P 106 328
+P 106 332
+P 106 336
+P 106 340
+P 94 340
+P 94 336
+P 94 332
+P 94 328
+P 94 324
+P 94 320
+P 94 316
+P 94 312
+P 94 308
+P 94 304
+P 68 466
+P 68 470
+P 68 474
+P 68 478
+P 68 482
+P 68 486
+P 68 490
+P 68 494
+P 68 498
+P 68 502
+P 68 506
+P 68 510
+P 56 510
+P 56 506
+P 56 502
+P 56 498
+P 56 494
+P 56 490
+P 56 486
+P 56 482
+P 56 478
+P 56 474
+P 56 470
+P 56 466
+P 108 466
+P 108 470
+P 108 474
+P 108 478
+P 108 482
+P 108 486
+P 108 490
+P 108 494
+P 96 494
+P 96 490
+P 96 486
+P 96 482
+P 96 478
+P 96 474
+P 96 470
+P 96 466
+P 18 432
+P 22 432
+P 26 432
+P 30 432
+P 34 432
+P 38 432
+P 42 432
+P 46 432
+P 50 432
+P 54 432
+P 54 444
+P 50 444
+P 46 444
+P 42 444
+P 38 444
+P 34 444
+P 30 444
+P 26 444
+P 22 444
+P 18 444
+P 74 432
+P 78 432
+P 82 432
+P 86 432
+P 90 432
+P 94 432
+P 98 432
+P 102 432
+P 106 432
+P 110 432
+P 110 444
+P 106 444
+P 102 444
+P 98 444
+P 94 444
+P 90 444
+P 86 444
+P 82 444
+P 78 444
+P 74 444
+P 144 8
+P 140 8
+P 136 8
+P 132 8
+P 128 8
+P 124 8
+P 120 8
+P 116 8
+P 112 8
+P 108 8
+P 104 8
+P 100 8
+P 96 8
+P 92 8
+P 88 8
+P 84 8
+P 80 8
+P 76 8
+P 72 8
+P 68 8
+P 64 8
+P 60 8
+P 56 8
+P 52 8
+P 48 8
+P 44 8
+P 40 8
+P 36 8
+P 32 8
+P 28 8
+P 24 8
+P 20 8
+P 144 12
+P 140 12
+P 136 12
+P 132 12
+P 128 12
+P 124 12
+P 120 12
+P 116 12
+P 112 12
+P 108 12
+P 104 12
+P 100 12
+P 96 12
+P 92 12
+P 88 12
+P 84 12
+P 80 12
+P 76 12
+P 72 12
+P 68 12
+P 64 12
+P 60 12
+P 56 12
+P 52 12
+P 48 12
+P 44 12
+P 40 12
+P 36 12
+P 32 12
+P 28 12
+P 24 12
+P 20 12
+P 144 16
+P 140 16
+P 136 16
+P 132 16
+P 128 16
+P 124 16
+P 120 16
+P 116 16
+P 112 16
+P 108 16
+P 104 16
+P 100 16
+P 96 16
+P 92 16
+P 88 16
+P 84 16
+P 80 16
+P 76 16
+P 72 16
+P 68 16
+P 64 16
+P 60 16
+P 56 16
+P 52 16
+P 48 16
+P 44 16
+P 40 16
+P 36 16
+P 32 16
+P 28 16
+P 24 16
+P 20 16
+P 76 406
+P 80 406
+P 84 406
+P 88 406
+P 92 406
+P 96 406
+P 100 406
+P 104 406
+P 104 418
+P 100 418
+P 96 418
+P 92 418
+P 88 418
+P 84 418
+P 80 418
+P 76 418
+P 28 318
+P 28 322
+P 28 326
+P 28 330
+P 28 334
+P 28 338
+P 28 342
+P 28 346
+P 16 346
+P 16 342
+P 16 338
+P 16 334
+P 16 330
+P 16 326
+P 16 322
+P 16 318
+P 26 540
+P 26 544
+P 26 548
+P 26 552
+P 26 556
+P 26 560
+P 26 564
+P 14 564
+P 14 560
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to