66 lines
1.5 KiB
Python
66 lines
1.5 KiB
Python
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
|
|
class Carry:
|
|
def __init__(self, arr):
|
|
if not isinstance(arr, np.ndarray):
|
|
arr = np.array(arr)
|
|
overflow = None
|
|
over_pos = None
|
|
coeff_sum = 0
|
|
#find largest carry
|
|
for i, row in enumerate(arr):
|
|
for j, val in enumerate(row):
|
|
coeff_sum += val
|
|
if val > 0:
|
|
if overflow is not None:
|
|
raise ValueError("array supplied has more than one overflow digit")
|
|
overflow = val
|
|
over_pos = (i, j)
|
|
|
|
if coeff_sum < 0:
|
|
raise ValueError("sum of coefficients too small")
|
|
|
|
self._arr = arr
|
|
self.over_pos = over_pos
|
|
self.overflow = overflow
|
|
|
|
def _update(self, base, update_tuples, zerowall):
|
|
#dim_x, dim_y = base.shape
|
|
pos_x, pos_y = self.over_pos
|
|
for (x,y) in update_tuples:
|
|
idx = base[(x,y)]
|
|
dec = (idx // self.overflow) # - 1
|
|
|
|
wall = zerowall.copy()
|
|
sh_x, sh_y = self._arr.shape
|
|
x -= pos_x
|
|
y -= pos_y
|
|
|
|
wall[x:x + sh_x, y:y + sh_y] = dec * self._arr
|
|
base -= wall
|
|
|
|
def update(self, base):
|
|
zerowall = np.zeros(base.shape, dtype=base.dtype)
|
|
while True:
|
|
update_tuples = list(zip(*np.where(base >= self.overflow)))
|
|
if not update_tuples:
|
|
break
|
|
self._update(base, update_tuples, zerowall)
|
|
|
|
def times(self, base, val, center=(0,0)):
|
|
#perform multiplication using the carry
|
|
base[center] *= val
|
|
self.update(base)
|
|
return base
|
|
|
|
def add(self, base, val=1, center=(0,0)):
|
|
base[center] += val
|
|
self.update(base)
|
|
return base
|
|
|
|
laplace = Carry(np.array([[0,-1,0],[-1,4,-1],[0,-1,0]]))
|
|
|
|
#test = np.zeros((100, 100))
|
|
#test[50,50] = 4
|