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