Skip to content

Commit 3fffae7

Browse files
Release bridge v0.2.0 (#106)
Co-authored-by: Hylke Donker <h.c.donker@umcg.nl>
1 parent 97df994 commit 3fffae7

File tree

3 files changed

+122
-13
lines changed

3 files changed

+122
-13
lines changed

recipes/bridge/README.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,33 @@
66

77
This package acts as a bridge between Mojo native types and those from the Python world.
88

9-
Example usage, to convert a NumPy array to a Mojo tensor:
9+
Example usage, to convert a NumPy array to a Mojo `LayoutTensor` or `Tensor`:
1010
```mojo
1111
from python import Python
12-
from bridge.numpy import ndarray_to_tensor
12+
from bridge.numpy import ndarray_to_layouttensor, ndarray_to_tensor
1313
1414
var np = Python.import_module("numpy")
1515
np_array = np.arange(6.0).reshape(2,3)
16-
mojo_tensor = ndarray_to_tensor[DType.float64](np_array)
16+
17+
# Convert to new-style `LayoutTensor`.
18+
mojo_tensor = ndarray_to_layouttensor[order=2](np_array)
19+
20+
# Convert to old-style `Tensor`.
21+
mojo_oldtensor = ndarray_to_tensor[DType.float64](np_array)
1722
```
1823
Or to achieve the reverse:
1924
```mojo
2025
from tensor import Tensor
2126
22-
from bridge.numpy import tensor_to_ndarray
27+
from bridge.numpy import layouttensor_to_ndarray, tensor_to_ndarray
28+
29+
# Convert new-style `LayoutTensor` to numpy array.
30+
np_array = layouttensor_to_ndarray(mojo_tensor)
2331
32+
# Convert old-style `Tensor` to numpy array.
2433
values = List[Float64](0.0, 1.0, 2.0, 3.0, 4.0, 5.0)
25-
mojo_tensor = Tensor[DType.float64](shape=(2, 3), list=values)
26-
np_array = tensor_to_ndarray(mojo_tensor)
34+
mojo_oldtensor = Tensor[DType.float64](shape=(2, 3), list=values)
35+
np_array = tensor_to_ndarray(mojo_oldtensor)
2736
```
2837

2938
# Installation

recipes/bridge/recipe.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
context:
2-
version: "0.1.0"
2+
version: "0.2.0"
33

44
package:
55
name: "bridge"
66
version: ${{ version }}
77

88
source:
99
- git: https://gitlab.com/hylkedonker/bridge.git
10-
rev: dc89432cb79b6eeef42e1755593ea3837c48d7dd
10+
rev: 87f10144b004ff4ef8e73d6b8b52e3f81effd40f
1111

1212
build:
1313
number: 0
1414
script:
1515
- mojo package src/bridge -o ${{ PREFIX }}/lib/mojo/bridge.mojopkg
1616
requirements:
1717
host:
18-
- max=25.1
18+
- max=25.2
1919
run:
2020
- ${{ pin_compatible('max') }}
2121

recipes/bridge/test_numpy.🔥

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
from python import Python
2-
from tensor import Tensor, rand
3-
from testing import assert_true, assert_equal
2+
from layout import Layout, LayoutTensor
3+
from tensor import Tensor
4+
from testing import assert_equal, assert_raises, assert_true
45

5-
from bridge.numpy import ndarray_to_tensor, tensor_to_ndarray
6+
from bridge.numpy import (
7+
layouttensor_to_ndarray,
8+
ndarray_to_layouttensor,
9+
ndarray_to_tensor,
10+
tensor_to_ndarray,
11+
)
612

713

814
def test_tensor_identity_transformation():
@@ -14,10 +20,104 @@ def test_tensor_identity_transformation():
1420
assert_equal(in_matrix, out_matrix)
1521

1622

17-
def test_numpy_identity_transformation():
23+
def test_numpy_tensor_identity_transformation():
1824
"""Test that `tensor_to_ndarray` is inverse of `ndarray_to_tensor`."""
1925
var np = Python.import_module("numpy")
2026
var in_array = np.arange(6).reshape(3, 2)
2127
var tensor = ndarray_to_tensor[DType.float64](in_array)
2228
var out_array = tensor_to_ndarray(tensor)
2329
assert_equal(in_array, out_array)
30+
31+
32+
def test_ndarray_to_layouttensor():
33+
"""Test numpy array conversion to layouttensor for various tensor shapes."""
34+
var np = Python.import_module("numpy")
35+
36+
# 1) Test vectors
37+
var in_vector = np.arange(4.0)
38+
var out_vector = ndarray_to_layouttensor[order=1](in_vector)
39+
assert_equal(out_vector[1], 1.0)
40+
assert_equal(out_vector[3], 3.0)
41+
42+
# 2) Test matrices
43+
var in_matrix = np.arange(4.0 * 3.0).reshape(3, 4)
44+
var out_matrix = ndarray_to_layouttensor[order=2](in_matrix)
45+
assert_equal(out_matrix[0, 0], 0.0)
46+
assert_equal(out_matrix[1, 1], 5.0)
47+
assert_equal(out_matrix[1, 3], 7.0)
48+
assert_equal(out_matrix[2, 1], 9.0)
49+
50+
# Check that non-contiguous arrays raise exceptions.
51+
with assert_raises():
52+
var in_matrix_col_major = np.asfortranarray(in_matrix)
53+
_ = ndarray_to_layouttensor[order=2](in_matrix_col_major)
54+
55+
# 3) Test three-index tensors
56+
var in_tensor = np.arange(4.0 * 3.0).reshape(3, 1, 4)
57+
var out_tensor = ndarray_to_layouttensor[order=3](in_tensor)
58+
assert_equal(out_tensor[0, 0, 0], 0.0)
59+
assert_equal(out_tensor[1, 0, 1], 5.0)
60+
assert_equal(out_tensor[1, 0, 3], 7.0)
61+
assert_equal(out_tensor[2, 0, 1], 9.0)
62+
63+
# 3) Test four-index tensors
64+
var in_4tensor = np.arange(4.0 * 3.0).reshape(2, 3, 1, 2)
65+
var out_4tensor = ndarray_to_layouttensor[order=4](in_4tensor)
66+
assert_equal(out_4tensor[0, 0, 0, 0], 0.0)
67+
assert_equal(out_4tensor[0, 1, 0, 1], 3.0)
68+
assert_equal(out_4tensor[1, 0, 0, 1], 7.0)
69+
assert_equal(out_4tensor[0, 2, 0, 0], 4.0)
70+
71+
72+
def test_memory_leaks():
73+
"""Test that we can safely remove the reference to the numpy array."""
74+
var np = Python.import_module("numpy")
75+
var np_array = np.arange(6.0).reshape(3, 2)
76+
var tensor = ndarray_to_layouttensor[order=2](np_array)
77+
np_array.__del__()
78+
assert_equal(tensor[1, 0], 2.0)
79+
assert_equal(tensor[1, 1], 3.0)
80+
assert_equal(tensor[2, 1], 5.0)
81+
82+
83+
# def test_layouttensor_numpy_identity_transformation():
84+
# """Test that `layouttensor_to_ndarray` is inverse of `ndarray_to_layouttensor`.
85+
# """
86+
# values = List[Float64](0.0, 1.0, 2.0, 3.0, 4.0, 5.0)
87+
# tensor = Tensor[DType.float64](shape=(2, 3), list=values)
88+
# var ptr = tensor.unsafe_ptr()
89+
# layouttensor = LayoutTensor[
90+
# mut=False,
91+
# DType.float64,
92+
# Layout.row_major(2, 3),
93+
# __origin_of(ptr[]),
94+
# ](ptr=ptr)
95+
# np_array = layouttensor_to_ndarray(layouttensor)
96+
# out_layouttensor = ndarray_to_layouttensor[order=2](in_array)
97+
98+
99+
def test_numpy_layouttensor_identity_transformation():
100+
"""Test that `ndarray_to_layouttensor` is the inverse of `layouttensor_to_ndarray`.
101+
"""
102+
var np = Python.import_module("numpy")
103+
104+
# 1) Test vectors
105+
# TODO: Add support for vectors!
106+
107+
# 2) Test matrices
108+
var in_matrix = np.arange(4.0 * 3.0).reshape(3, 4)
109+
var layout_matrix = ndarray_to_layouttensor[order=2](in_matrix)
110+
var out_matrix = layouttensor_to_ndarray(layout_matrix)
111+
np.testing.assert_array_equal(in_matrix, out_matrix)
112+
113+
# 3) Test three-index tensors
114+
var in_tensor = np.arange(4.0 * 3.0).reshape(3, 1, 4)
115+
var layout_tensor = ndarray_to_layouttensor[order=3](in_tensor)
116+
var out_tensor = layouttensor_to_ndarray(layout_tensor)
117+
np.testing.assert_array_equal(in_tensor, out_tensor)
118+
119+
# 3) Test four-index tensors
120+
var in_4tensor = np.arange(4.0 * 3.0).reshape(2, 3, 1, 2)
121+
var layout_4tensor = ndarray_to_layouttensor[order=4](in_4tensor)
122+
var out_4tensor = layouttensor_to_ndarray(layout_4tensor)
123+
np.testing.assert_array_equal(in_4tensor, out_4tensor)

0 commit comments

Comments
 (0)