From 540f54fbf9566334b4a25648995a31a67e13996a Mon Sep 17 00:00:00 2001 From: MadAlex1997 Date: Fri, 30 Aug 2024 13:49:53 -0400 Subject: [PATCH] Simplify shape based initializers, add tests for shape based initializers --- numojo/__init__.mojo | 2 + numojo/core/ndarray.mojo | 184 ++++++++++----------------------- tests/test_array_creation.mojo | 46 +++++++-- 3 files changed, 97 insertions(+), 135 deletions(-) diff --git a/numojo/__init__.mojo b/numojo/__init__.mojo index 6bc722f..5d3d916 100644 --- a/numojo/__init__.mojo +++ b/numojo/__init__.mojo @@ -6,6 +6,8 @@ from .core import * from .math import * from .math.statistics import stats +alias __version__ = "V0.2" + # Constants alias pi = core.constants.Constants.pi alias e = core.constants.Constants.e diff --git a/numojo/core/ndarray.mojo b/numojo/core/ndarray.mojo index ba61457..c75cea6 100644 --- a/numojo/core/ndarray.mojo +++ b/numojo/core/ndarray.mojo @@ -653,84 +653,34 @@ struct NDArray[dtype: DType = DType.float64]( # ===-------------------------------------------------------------------===# # default constructor - @always_inline("nodebug") - fn __init__( - inout self, *shape: Int, random: Bool = False, order: String = "C" - ) raises: - """ - NDArray initialization for variadic shape. - - Args: - shape: Variadic shape. - random: Set the values randomly. - order: Memory order C or F. - - Example: - NDArray[DType.int8](3,2,4) - Returns an zero array with shape 3 x 2 x 4. - """ - self.ndim = shape.__len__() - # I cannot name self.ndshape as self.shape as lsp gives unrecognized variable error - self.ndshape = NDArrayShape(shape) - self.stride = NDArrayStride(shape, offset=0, order=order) - # I gotta make coefficients empty, but let's just keep it like for now - self.coefficient = NDArrayStride(shape, offset=0, order=order) - self.datatype = dtype - self.order = order - self.data = DTypePointer[dtype].alloc(self.ndshape.ndsize) - memset_zero(self.data, self.ndshape.ndsize) - if random: - rand[dtype](self.data, self.ndshape.ndsize) - @always_inline("nodebug") fn __init__( inout self, - shape: List[Int], + *shape: Int, + fill: Scalar[dtype] = Scalar[dtype](0), random: Bool = False, order: String = "C", ) raises: """ - NDArray initialization for list shape. + NDArray initialization for variadic shape with option to fill. Args: - shape: List of shape. - random: Set the values randomly. + shape: Variadic shape. + fill: Set all the values to this. + random: Set values randomly. order: Memory order C or F. Example: NDArray[DType.float16](VariadicList[Int](3, 2, 4), random=True) Returns an array with shape 3 x 2 x 4 and randomly values. """ - self.ndim = shape.__len__() - self.ndshape = NDArrayShape(shape) - self.stride = NDArrayStride(shape, offset=0, order=order) - self.coefficient = NDArrayStride(shape, offset=0, order=order) - self.data = DTypePointer[dtype].alloc(self.ndshape.ndsize) - memset_zero(self.data, self.ndshape.ndsize) - self.datatype = dtype - self.order = order - if random: - rand[dtype](self.data, self.ndshape.ndsize) - @always_inline("nodebug") - fn __init__( - inout self, - shape: VariadicList[Int], - random: Bool = False, - order: String = "C", - ) raises: - """ - NDArray initialization for variadic shape. - - Args: - shape: Variadic List shape. - random: Set the values randomly. - order: Memory order C or F. + if random == True and fill != 0: + raise Error( + "numojo/core/ndarray:NDArray: __init__(*shape, fill, random)):" + " Error if random is true you cannot set a fill value" + ) - Example: - NDArray[DType.float16](VariadicList[Int](3, 2, 4), random=True) - Returns an array with shape 3 x 2 x 4 and randomly values. - """ self.ndim = shape.__len__() self.ndshape = NDArrayShape(shape) self.stride = NDArrayStride(shape, offset=0, order=order) @@ -741,42 +691,16 @@ struct NDArray[dtype: DType = DType.float64]( self.order = order if random: rand[dtype](self.data, self.ndshape.ndsize) - - @always_inline("nodebug") - fn __init__( - inout self, - *shape: Int, - fill: Scalar[dtype], - order: String = "C", - ) raises: - """ - NDArray initialization for variadic shape with option to fill. - - Args: - shape: Variadic shape. - fill: Set all the values to this. - order: Memory order C or F. - - Example: - NDArray[DType.float16](VariadicList[Int](3, 2, 4), random=True) - Returns an array with shape 3 x 2 x 4 and randomly values. - """ - self.ndim = shape.__len__() - self.ndshape = NDArrayShape(shape) - self.stride = NDArrayStride(shape, offset=0, order=order) - self.coefficient = NDArrayStride(shape, offset=0, order=order) - self.data = DTypePointer[dtype].alloc(self.ndshape.ndsize) - memset_zero(self.data, self.ndshape.ndsize) - self.datatype = dtype - self.order = order - for i in range(self.ndshape.ndsize): - self.data[i] = fill + else: + for i in range(self.ndshape.ndsize): + self.data[i] = fill @always_inline("nodebug") fn __init__( inout self, shape: List[Int], - fill: Scalar[dtype], + fill: Scalar[dtype] = Scalar[dtype](0), + random: Bool = False, order: String = "C", ) raises: """ @@ -785,12 +709,20 @@ struct NDArray[dtype: DType = DType.float64]( Args: shape: List of shape. fill: Set all the values to this. + random: Set values randomly. order: Memory order C or F. Example: NDArray[DType.float16](VariadicList[Int](3, 2, 4), random=True) Returns an array with shape 3 x 2 x 4 and randomly values. """ + + if random == True and fill != 0: + raise Error( + "numojo/core/ndarray:NDArray: __init__(List[Int], fill," + " random)): Error if random is true you cannot set a fill value" + ) + self.ndim = shape.__len__() self.ndshape = NDArrayShape(shape) self.stride = NDArrayStride(shape, offset=0, order=order) @@ -799,14 +731,18 @@ struct NDArray[dtype: DType = DType.float64]( memset_zero(self.data, self.ndshape.ndsize) self.datatype = dtype self.order = order - for i in range(self.ndshape.ndsize): - self.data[i] = fill + if random: + rand[dtype](self.data, self.ndshape.ndsize) + else: + for i in range(self.ndshape.ndsize): + self.data[i] = fill @always_inline("nodebug") fn __init__( inout self, shape: VariadicList[Int], - fill: Scalar[dtype], + fill: Scalar[dtype] = Scalar[dtype](0), + random: Bool = False, order: String = "C", ) raises: """ @@ -815,12 +751,19 @@ struct NDArray[dtype: DType = DType.float64]( Args: shape: Variadic List of shape. fill: Set all the values to this. + random: Set values randomly. order: Memory order C or F. Example: NDArray[DType.float16](VariadicList[Int](3, 2, 4), random=True) Returns an array with shape 3 x 2 x 4 and randomly values. """ + if random == True and fill != 0: + raise Error( + "numojo/core/ndarray:NDArray: __init__(VariadicList[Int], fill," + " random)): Error if random is true you cannot set a fill value" + ) + self.ndim = shape.__len__() self.ndshape = NDArrayShape(shape) self.stride = NDArrayStride(shape, offset=0, order=order) @@ -829,44 +772,18 @@ struct NDArray[dtype: DType = DType.float64]( memset_zero(self.data, self.ndshape.ndsize) self.datatype = dtype self.order = order - for i in range(self.ndshape.ndsize): - self.data[i] = fill - - @always_inline("nodebug") - fn __init__( - inout self, - shape: NDArrayShape, - random: Bool = False, - order: String = "C", - ) raises: - """ - NDArray initialization for NDArrayShape. - - Args: - shape: Variadic shape. - random: Set all the values randomly. - order: Memory order C or F. - - Example: - NDArray[DType.float16](VariadicList[Int](3, 2, 4), random=True) - Returns an array with shape 3 x 2 x 4 and randomly values. - """ - self.ndim = shape.ndlen - self.ndshape = NDArrayShape(shape) - self.stride = NDArrayStride(shape, order=order) - self.coefficient = NDArrayStride(shape, order=order) - self.data = DTypePointer[dtype].alloc(self.ndshape.ndsize) - memset_zero(self.data, self.ndshape.ndsize) - self.datatype = dtype - self.order = order if random: rand[dtype](self.data, self.ndshape.ndsize) + else: + for i in range(self.ndshape.ndsize): + self.data[i] = fill @always_inline("nodebug") fn __init__( inout self, shape: NDArrayShape, - fill: Scalar[dtype], + fill: Scalar[dtype] = Scalar[dtype](0), + random: Bool = False, order: String = "C", ) raises: """ @@ -875,12 +792,20 @@ struct NDArray[dtype: DType = DType.float64]( Args: shape: Variadic shape. fill: Set all the the values to this. + random: Set values randomly. order: Memory order C or F. Example: NDArray[DType.float16](VariadicList[Int](3, 2, 4), random=True) Returns an array with shape 3 x 2 x 4 and randomly values. """ + + if random == True and fill != 0: + raise Error( + "numojo/core/ndarray:NDArray: __init__(NDArrayShape, fill," + " random)): Error if random is true you cannot set a fill value" + ) + self.ndim = shape.ndlen self.ndshape = NDArrayShape(shape) self.stride = NDArrayStride(shape, order=order) @@ -889,8 +814,11 @@ struct NDArray[dtype: DType = DType.float64]( memset_zero(self.data, self.ndshape.ndsize) self.datatype = dtype self.order = order - for i in range(self.ndshape.ndsize): - self.data[i] = fill + if random: + rand[dtype](self.data, self.ndshape.ndsize) + else: + for i in range(self.ndshape.ndsize): + self.data[i] = fill fn __init__( inout self, diff --git a/tests/test_array_creation.mojo b/tests/test_array_creation.mojo index a6881c4..19fa7d9 100644 --- a/tests/test_array_creation.mojo +++ b/tests/test_array_creation.mojo @@ -2,6 +2,35 @@ import numojo as nm from time import now from python import Python, PythonObject from utils_for_test import check, check_is_close +from testing.testing import assert_raises + + +def test_list_creation_methods(): + var np = Python.import_module("numpy") + check( + nm.NDArray(5, 5, 5, fill=5), + np.zeros([5, 5, 5], dtype=np.float64) + 5, + "*shape broken", + ) + check( + nm.NDArray(List[Int](5, 5, 5), fill=5), + np.zeros([5, 5, 5], dtype=np.float64) + 5, + "List[int] shape broken", + ) + check( + nm.NDArray(VariadicList[Int](5, 5, 5), fill=5), + np.zeros([5, 5, 5], dtype=np.float64) + 5, + "VariadicList[Int] shape broken", + ) + check( + nm.NDArray(nm.NDArrayShape(5, 5, 5), fill=5), + np.zeros([5, 5, 5], dtype=np.float64) + 5, + "NDArrayShape shape broken", + ) + with assert_raises( + contains="Error if random is true you cannot set a fill value" + ): + _ = nm.NDArray(nm.NDArrayShape(5, 5, 5), fill=5, random=True) def test_arange(): @@ -91,20 +120,23 @@ def test_eye(): def main(): + # var np = Python.import_module("numpy") + # var arr = nm.arange[nm.f64](0, 100) + # arr.reshape(10, 10) + # var np_arr = np.arange(0, 100).reshape(10, 10) var np = Python.import_module("numpy") - var arr = nm.arange[nm.f64](0, 100) - arr.reshape(10, 10) - var np_arr = np.arange(0, 100).reshape(10, 10) + print(nm.NDArray(5, 5, 5, fill=5).shape()) + print(np.zeros([5, 5, 5], dtype=np.float64).fill(5)) # Arange like flat arrays # check(nm.arange[nm.i64](0,100),np.arange(0,100,dtype=np.int64),"Arange is broken") # check(nm.linspace[nm.i64](0,100),np.linspace(0,100,dtype=np.float64),"Linspace is broken") # check_is_close(nm.logspace[nm.i64](0,100,5),np.logspace(0,100,5,dtype=np.float64),"Logspace is broken") # check_is_close(nm.geomspace[nm.i64](1,100,5),np.geomspace(1,100,5,dtype=np.float64),"Logspace is broken") # print((arr@arr).to_numpy()-np.matmul(np_arr,np_arr)) - print( - nm.matmul_naive[nm.f64](arr, arr).to_numpy() - ) # -np.matmul(np_arr,np_arr)) - print(np.matmul(np_arr, np_arr)) + # print( + # nm.matmul_naive[nm.f64](arr, arr).to_numpy() + # ) # -np.matmul(np_arr,np_arr)) + # print(np.matmul(np_arr, np_arr)) # # Basic ND arrays # print(nm.sin[nm.f64](nm.arange[nm.f64](0,15))) # print( np.sin(np.arange(0,15, dtype=np.float64)))