Skip to content

Commit

Permalink
Merge pull request #28 from Bchass/meshgrid
Browse files Browse the repository at this point in the history
Meshgrid
  • Loading branch information
Bchass authored Nov 25, 2024
2 parents 55d4768 + a544913 commit 3f480c1
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 3 deletions.
4 changes: 1 addition & 3 deletions tinynumpy/tests/test_tinyndarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
except ImportError:
numpy = tinynumpy

#numpy.set_printoptions(formatter={'float': repr})

def _clean_repr(a):
return "".join(repr(a).split())
return "".join(repr(a).replace('.', '').split())

class TestNDArray(unittest.TestCase):
def setUp(self):
Expand Down
142 changes: 142 additions & 0 deletions tinynumpy/tests/test_tinynumpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,149 @@ def test_logspace():
result = tnp.logspace(2.0, 3.0, num=4, base=[2.0, 3.0], axis=-1)
expected_result = tnp.array([9.0, 12.980246132766677, 18.720754407467133, 27.0])
assert all(result[i] == expected_result[i] for i in range(len(result)))

def test_meshgrid():
"""test the meshgrid function for tinynumpy"""
# Cartesian indexing
nx, ny = (3, 2)
x = tnp.linspace(0, 1, nx)
y = tnp.linspace(0, 1, ny)
xv, yv = tnp.meshgrid(x, y, indexing='xy')

xv_expected_result = tnp.array([[0.0, 0.0],
[0.5, 0.5],
[1.0, 1.0]])

yv_expected_result = tnp.array([[0.0, 1.0],
[0.0, 1.0],
[0.0, 1.0]])

assert (xv == xv_expected_result).all()
assert (yv == yv_expected_result).all()

# Matrix indexing
ni, nj = (3, 2)
i = tnp.linspace(0, 1, ni)
j = tnp.linspace(0, 1, nj)
iv, jv = tnp.meshgrid(i, j, indexing='ij', sparse=True)

iv_expected_result = tnp.array([0.0, 0.5, 1.0])

jv_expected_result = tnp.array([0.0, 1.0])

assert (iv == iv_expected_result).all()
assert (jv == jv_expected_result).all()

# coordiante arrays
x = tnp.linspace(-5, 5, 101)
y = tnp.linspace(-5, 5, 101)
xx, yy = tnp.meshgrid(x,y)
zz = tnp.sqrt(xx**2 + yy**2)

xx_shape_expected = (101, 101)
yy_shape_expected = (101, 101)
zz_shape_expected = (101, 101)

assert (xx.shape == xx_shape_expected)
assert (yy.shape == yy_shape_expected)
assert (zz.shape == zz_shape_expected)

# value error for indexing
with pytest.raises(ValueError):
xv, yv = tnp.meshgrid(x, y, indexing='xi')

# value error for len shapes < 1
with pytest.raises(ValueError):
xv, yv = tnp.meshgrid(x, indexing='xy')

def test_sqrt():
"""Test the sqrt function for tinynumpy."""

# --- Scalar values ---
# Positive integer
x = tnp.sqrt(2)
expected_result = float(1.4142135623730951)
assert x == expected_result

# Positive float
x = tnp.sqrt(4.0)
expected_result = float(2.0)
assert x == expected_result

# Zero
x = tnp.sqrt(0)
expected_result = float(0.0)
assert x == expected_result

# Negative number (returns nan)
x = tnp.sqrt(-1)
expected_result = 'nan'
assert str(x) == str(expected_result)

# Large number
x = tnp.sqrt(1e16)
expected_result = float(100000000.0)
assert x == expected_result

# Small number
x = tnp.sqrt(1e-16)
expected_result = float(1e-08)
assert x == expected_result

# Multi-dimensional
x = tnp.sqrt(tnp.array([[1, 4], [9, 16]]))
expected_result = tnp.array([[1, 2],
[3, 4]])
assert x == expected_result

# Zero
x = tnp.sqrt(0)
expected_result = float(0.0)
assert x == expected_result

# --- Lists ---
# Simple positive list
x = tnp.sqrt([1, 4, 9])
expected_result = ['1.', '2.', '3.']
assert x == expected_result

# List with negative number
x = tnp.sqrt([1, -4, 9])
expected_result = ['1.', 'nan', '3.']
assert x == expected_result

# Mixed
x = tnp.sqrt([1, 4.0, 9])
expected_result = ['1.', '2.', '3.']
assert x == expected_result

# Nested lists
x = tnp.sqrt([[1, 4], [9, 16]])
expected_result = [['1.', '2.'], ['3.', '4.']]
assert x == expected_result

# Empty input
x = tnp.sqrt([])
expected_result = []
assert x == expected_result

# --- Error handling ---
# Complex numbers (unsupported)
with pytest.raises(TypeError):
tnp.sqrt([4, -1, -3+4J])

# non-numeric types
with pytest.raises(TypeError):
tnp.sqrt("string")

with pytest.raises(TypeError):
tnp.sqrt(None)

# Make sure no modifcations are done
x = tnp.array([1, 4, 9])
result = tnp.sqrt(x)
assert x._toflatlist() == [1, 4, 9]

def test_astype():
"""test the astype function for tinynumpy"""
for dtype in ['bool', 'int8', 'uint8', 'int16', 'uint16',
Expand Down
78 changes: 78 additions & 0 deletions tinynumpy/tinynumpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,11 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):
return a

def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=None):
""" logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=None)
Return numbers spaced evenly on a log scale.
"""

start, stop = float(start), float(stop)
ra = stop - start
Expand All @@ -382,6 +387,54 @@ def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=Non

return a


def meshgrid(*xi, copy=True, sparse=False, indexing='xy'):
""" meshgrid(*xi, copy=True, sparse=False, indexing='xy')
Return a tuple of coordinate matrices from coordinate vectors.
"""

ndim = len(xi)

if indexing not in {'xy', 'ij'}:
raise ValueError("Indexing must be 'xy' or 'ij'")

# Adjust the order of inputs for 'xy' indexing
if indexing == 'xy' and ndim > 1:
xi = (xi[1], xi[0]) + xi[2:]

# Get the lengths of each input array
shapes = [len(x) for x in xi]

if len(shapes) < 2:
raise ValueError("At least two input arrays are required")

# Create the output grids
grids = []
if not sparse:
for i, x in enumerate(xi):
if i == 0:
# Repeat for columns (x-axis direction)
grid = [list(x) for _ in range(shapes[1])]
print(grid)
else:
# Repeat for rows (y-axis direction)
grid = [[x_val] * shapes[0] for x_val in x]
grids.append(array(grid))
else:
for i, x in enumerate(xi):
shape = [1] * ndim
shape[i] = len(x)
grids.append(array(x))

# Swap back grids if 'xy' indexing
if indexing == 'xy' and ndim >= 2:
grids[0], grids[1] = grids[1], grids[0]

return tuple(grids)


def add(ndarray_vec1, ndarray_vec2):
c = []
for a, b in zip(ndarray_vec1, ndarray_vec2):
Expand Down Expand Up @@ -484,6 +537,31 @@ def asfortranarray(self):
return out


def sqrt(x):
"""
Returns:
ndarry: Array with dtype of float64
list: List with sqrt applied
"""

if isinstance(x, ndarray):
# create arr of same shape and dtype
out = empty(x.shape, dtype="float64")
# apply sqrt
out._data[:] = [value**0.5 if value >= 0 else nan for value in x._toflatlist()]
return out
elif isinstance(x, (int, float)):
return x**0.5 if x >= 0 else float('nan')
# list
elif isinstance(x, list):
return [sqrt(i) if isinstance(i, list) else str(i**0.5).rstrip('0') if i >= 0 else 'nan' for i in x]
else:
raise TypeError("Unsupported type for sqrt")



class ndarray(object):
""" ndarray(shape, dtype='float64', buffer=None, offset=0,
strides=None, order=None)
Expand Down

0 comments on commit 3f480c1

Please sign in to comment.