Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,11 @@ from numojo.prelude import *

fn main() raises:
# Create a complexscalar 5 + 5j
var complexscalar = ComplexSIMD[cf32](re=5, im=5)
var complexscalar = ComplexSIMD[f32](re=5, im=5)
# Create complex array filled with (5 + 5j)
var A = nm.full[cf32](Shape(1000, 1000), fill_value=complexscalar)
var A = nm.full[f32](Shape(1000, 1000), fill_value=complexscalar)
# Create complex array filled with (1 + 1j)
var B = nm.ones[cf32](Shape(1000, 1000))
var B = nm.ones[f32](Shape(1000, 1000))

# Print array
print(A)
Expand Down
262 changes: 261 additions & 1 deletion numojo/core/_math_funcs.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,49 @@ struct Vectorized(Backend):
vectorize[closure, width](result_array.size)
return result_array

fn math_func_1_scalar_1_array_in_one_array_out[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
SIMD[type, simd_w], SIMD[type, simd_w]
) -> SIMD[type, simd_w],
](
self: Self, scalar: Scalar[dtype], array: NDArray[dtype]
) raises -> NDArray[dtype]:
"""
Apply a SIMD function of two variable and one return to a NDArray.

Parameters:
dtype: The element type.
func: The SIMD function to to apply.

Args:
scalar: A Scalars.
array: A NDArray.

Returns:
A a new NDArray that is NDArray with the function func applied.
"""

# For 0darray (numojo scalar)
# Treat it as a scalar and apply the function
if array.ndim == 0:
var result_array = _0darray(val=func[dtype, 1](scalar, array[]))
return result_array

var result_array: NDArray[dtype] = NDArray[dtype](array.shape)
alias width = simdwidthof[dtype]()

@parameter
fn closure[simdwidth: Int](i: Int):
var simd_data1 = array._buf.ptr.load[width=simdwidth](i)
var simd_data2 = scalar
result_array._buf.ptr.store(
i, func[dtype, simdwidth](simd_data2, simd_data1)
)

vectorize[closure, width](result_array.size)
return result_array

fn math_func_compare_2_arrays[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
Expand Down Expand Up @@ -606,6 +649,43 @@ struct VectorizedUnroll[unroll_factor: Int = 1](Backend):
vectorize[closure, width, unroll_factor=unroll_factor](array.size)
return result_array

fn math_func_1_scalar_1_array_in_one_array_out[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
SIMD[type, simd_w], SIMD[type, simd_w]
) -> SIMD[type, simd_w],
](
self: Self, scalar: Scalar[dtype], array: NDArray[dtype]
) raises -> NDArray[dtype]:
"""
Apply a SIMD function of two variable and one return to a NDArray.

Parameters:
dtype: The element type.
func: The SIMD function to to apply.

Args:
scalar: A Scalars.
array: A NDArray.

Returns:
A a new NDArray that is NDArray with the function func applied.
"""

var result_array: NDArray[dtype] = NDArray[dtype](array.shape)
alias width = simdwidthof[dtype]()

@parameter
fn closure[simdwidth: Int](i: Int):
var simd_data1 = array._buf.ptr.load[width=simdwidth](i)
var simd_data2 = scalar
result_array._buf.ptr.store(
i, func[dtype, simdwidth](simd_data2, simd_data1)
)

vectorize[closure, width, unroll_factor=unroll_factor](array.size)
return result_array

fn math_func_compare_2_arrays[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
Expand Down Expand Up @@ -1000,6 +1080,52 @@ struct Parallelized(Backend):
parallelize[par_closure](num_cores)
return result_array

fn math_func_1_scalar_1_array_in_one_array_out[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
SIMD[type, simd_w], SIMD[type, simd_w]
) -> SIMD[type, simd_w],
](
self: Self, scalar: Scalar[dtype], array: NDArray[dtype]
) raises -> NDArray[dtype]:
"""
Apply a SIMD function of two variable and one return to a NDArray.

Parameters:
dtype: The element type.
func: The SIMD function to to apply.

Args:
scalar: A Scalars.
array: A NDArray.

Returns:
A a new NDArray that is NDArray with the function func applied.
"""

var result_array: NDArray[dtype] = NDArray[dtype](array.shape)
alias width = 1
var num_cores: Int = num_physical_cores()
var comps_per_core: Int = array.size // num_cores

@parameter
fn par_closure(j: Int):
@parameter
fn closure[simdwidth: Int](i: Int):
var simd_data1 = array._buf.ptr.load[width=simdwidth](
i + comps_per_core * j
)
var simd_data2 = scalar
result_array._buf.ptr.store(
i + comps_per_core * j,
func[dtype, simdwidth](simd_data2, simd_data1),
)

vectorize[closure, width](comps_per_core)

parallelize[par_closure](num_cores)
return result_array

fn math_func_compare_2_arrays[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
Expand Down Expand Up @@ -1491,6 +1617,67 @@ struct VectorizedParallelized(Backend):
vectorize[remainder_closure, width](comps_remainder)
return result_array

fn math_func_1_scalar_1_array_in_one_array_out[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
SIMD[type, simd_w], SIMD[type, simd_w]
) -> SIMD[type, simd_w],
](
self: Self, scalar: Scalar[dtype], array: NDArray[dtype]
) raises -> NDArray[dtype]:
"""
Apply a SIMD function of two variable and one return to a NDArray.

Parameters:
dtype: The element type.
func: The SIMD function to to apply.

Args:
scalar: A Scalar.
array: A NDArray.

Returns:
A a new NDArray that is NDArray with the function func applied.
"""

var result_array: NDArray[dtype] = NDArray[dtype](array.shape)
alias width = simdwidthof[dtype]()
var num_cores: Int = num_physical_cores()
var comps_per_core: Int = array.size // num_cores
var comps_remainder: Int = array.size % num_cores
var remainder_offset: Int = num_cores * comps_per_core

@parameter
fn par_closure(j: Int):
@parameter
fn closure[simdwidth: Int](i: Int):
var simd_data1 = array._buf.ptr.load[width=simdwidth](
i + comps_per_core * j
)
var simd_data2 = scalar
result_array._buf.ptr.store(
i + comps_per_core * j,
func[dtype, simdwidth](simd_data2, simd_data1),
)

vectorize[closure, width](comps_per_core)

parallelize[par_closure](num_cores)

@parameter
fn remainder_closure[simdwidth: Int](i: Int):
var simd_data1 = array._buf.ptr.load[width=simdwidth](
i + remainder_offset
)
var simd_data2 = scalar
result_array._buf.ptr.store(
i + remainder_offset,
func[dtype, simdwidth](simd_data2, simd_data1),
)

vectorize[remainder_closure, width](comps_remainder)
return result_array

fn math_func_compare_2_arrays[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
Expand Down Expand Up @@ -2357,7 +2544,6 @@ struct Naive(Backend):
A a new NDArray that is NDArray with the function func applied.
"""
var result_array: NDArray[dtype] = NDArray[dtype](array.shape)

for i in range(array.size):
var simd_data1 = array._buf.ptr.load[width=1](i)
var simd_data2 = scalar
Expand All @@ -2366,6 +2552,37 @@ struct Naive(Backend):
)
return result_array

fn math_func_1_scalar_1_array_in_one_array_out[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
SIMD[type, simd_w], SIMD[type, simd_w]
) -> SIMD[type, simd_w],
](
self: Self, scalar: Scalar[dtype], array: NDArray[dtype]
) raises -> NDArray[dtype]:
"""
Apply a SIMD function of two variable and one return to a NDArray.

Parameters:
dtype: The element type.
func: The SIMD function to to apply.

Args:
scalar: A Scalar.
array: A NDArray.

Returns:
A a new NDArray that is NDArray with the function func applied.
"""
var result_array: NDArray[dtype] = NDArray[dtype](array.shape)
for i in range(array.size):
var simd_data1 = array._buf.ptr.load[width=1](i)
var simd_data2 = scalar
result_array.store[width=1](
i, func[dtype, 1](simd_data2, simd_data1)
)
return result_array

fn math_func_compare_2_arrays[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
Expand Down Expand Up @@ -2688,6 +2905,49 @@ struct VectorizedVerbose(Backend):
)
return result_array

fn math_func_1_scalar_1_array_in_one_array_out[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
SIMD[type, simd_w], SIMD[type, simd_w]
) -> SIMD[type, simd_w],
](
self: Self, scalar: Scalar[dtype], array: NDArray[dtype]
) raises -> NDArray[dtype]:
"""
Apply a SIMD function of two variable and one return to a NDArray.

Parameters:
dtype: The element type.
func: The SIMD function to to apply.

Args:
scalar: A Scalar.
array: A NDArray.

Returns:
A a new NDArray that is NDArray with the function func applied.
"""
var result_array: NDArray[dtype] = NDArray[dtype](array.shape)
alias width = simdwidthof[dtype]()
for i in range(0, width * (array.size // width), width):
var simd_data1 = array._buf.ptr.load[width=width](i)
var simd_data2 = scalar
result_array.store[width=width](
i, func[dtype, width](simd_data2, simd_data1)
)

if array.size % width != 0:
for i in range(
width * (array.size // width),
array.size,
):
var simd_data1 = array._buf.ptr.load[width=1](i)
var simd_data2 = scalar
result_array.store[width=1](
i, func[dtype, 1](simd_data2, simd_data1)
)
return result_array

fn math_func_compare_2_arrays[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
Expand Down
8 changes: 2 additions & 6 deletions numojo/core/complex/complex_ndarray.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -1672,12 +1672,8 @@ struct ComplexNDArray[dtype: DType = DType.float64](
"""
Enables `Scalar + ComplexNDArray`.
"""
var real: NDArray[dtype] = math.add[dtype](
self._re, other.cast[dtype]()
)
var imag: NDArray[dtype] = math.add[dtype](
self._im, other.cast[dtype]()
)
var real: NDArray[dtype] = math.add[dtype](self._re, other)
var imag: NDArray[dtype] = math.add[dtype](self._im, other)
return Self(real, imag)

fn __radd__(mut self, other: NDArray[dtype]) raises -> Self:
Expand Down
28 changes: 28 additions & 0 deletions numojo/core/traits/backend.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,34 @@ trait Backend:

...

fn math_func_1_scalar_1_array_in_one_array_out[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
SIMD[type, simd_w], SIMD[type, simd_w]
) -> SIMD[type, simd_w],
](
self: Self, scalar: Scalar[dtype], array: NDArray[dtype]
) raises -> NDArray[dtype]:
"""
Apply a SIMD function of two variable and one return to a NDArray.

Constraints:
Both arrays must have the same shape

Parameters:
dtype: The element type.
func: The SIMD function to to apply.

Args:
scalar: A Scalars.
array: A NDArray.

Returns:
A new NDArray that is NDArray with the function func applied.
"""

...

fn math_func_compare_2_arrays[
dtype: DType,
func: fn[type: DType, simd_w: Int] (
Expand Down
4 changes: 2 additions & 2 deletions numojo/routines/creation.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ from builtin.math import pow
from collections import Dict
from collections.optional import Optional
from memory import UnsafePointer, memset_zero, memset, memcpy
from algorithm.memory import parallel_memcpy
from python import PythonObject, Python
from sys import simdwidthof
from tensor import Tensor, TensorShape
Expand Down Expand Up @@ -2080,11 +2081,10 @@ fn array[
Returns:
An Array of given data, shape and order.
"""

A = NDArray[dtype](NDArrayShape(shape), order)
for i in range(A.size):
A._buf.ptr[i] = data[i]
return A^
return A


fn arrayC[
Expand Down
Loading