diff --git a/aidge_core/unit_tests/test_tensor.py b/aidge_core/unit_tests/test_tensor.py index a214a0e354c64b515d0a7ac24d81c85e116938ca..d479c98b20534daa804f6019b63d528883c2b568 100644 --- a/aidge_core/unit_tests/test_tensor.py +++ b/aidge_core/unit_tests/test_tensor.py @@ -10,16 +10,16 @@ SPDX-License-Identifier: EPL-2.0 import unittest import aidge_core - from functools import reduce + import numpy as np + class test_tensor(unittest.TestCase): - """ + """Test tensor binding """ def setUp(self): pass - def tearDown(self): pass @@ -35,10 +35,60 @@ class test_tensor(unittest.TestCase): idx = t.get_idx(coord) self.assertEqual(idx, i) -if __name__ == '__main__': - unittest.main() + def test_getavailable_backends(self): + self.assertTrue("cpu" in aidge_core.Tensor.get_available_backends()) + + def test_numpy_int_to_tensor(self): + np_array = np.arange(9).reshape(1,1,3,3).astype(np.int32) + # Numpy -> Tensor + t = aidge_core.Tensor(np_array) + self.assertEqual(t.dtype(), aidge_core.DataType.Int32) + for i_t, i_n in zip(t, np_array.flatten()): + self.assertTrue(i_t == i_n) + for i,j in zip(t.dims(), np_array.shape): + self.assertEqual(i,j) + def test_tensor_int_to_numpy(self): + np_array = np.arange(9).reshape(1,1,3,3) + # Numpy -> Tensor + t = aidge_core.Tensor(np_array) + # Tensor -> Numpy + nnarray = np.array(t) + for i_nn, i_n in zip(nnarray.flatten(), np_array.flatten()): + self.assertTrue(i_nn == i_n) + for i,j in zip(t.dims(), nnarray.shape): + self.assertEqual(i,j) + def test_numpy_int64_to_tensor(self): + np_array = np.arange(9).reshape(1,1,3,3).astype(np.int64) + # Numpy -> Tensor + t = aidge_core.Tensor(np_array) + self.assertEqual(t.dtype(), aidge_core.DataType.Int64) + for i_t, i_n in zip(t, np_array.flatten()): + self.assertTrue(i_t == i_n) + for i,j in zip(t.dims(), np_array.shape): + self.assertEqual(i,j) + def test_numpy_float_to_tensor(self): + t = aidge_core.Tensor() + np_array = np.random.rand(1, 1, 3, 3).astype(np.float32) + # Numpy -> Tensor + t = aidge_core.Tensor(np_array) + self.assertEqual(t.dtype(), aidge_core.DataType.Float32) + for i_t, i_n in zip(t, np_array.flatten()): + self.assertTrue(i_t == i_n) # TODO : May need to change this to a difference + for i,j in zip(t.dims(), np_array.shape): + self.assertEqual(i,j) + def test_get_set(self): + dims = [2,2,2] + np_array = np.arange(8).reshape(dims).astype(np.int32) + # Numpy -> Tensor + t = aidge_core.Tensor(np_array) + for i in range(8): + self.assertEqual(t[i], i) + t[i] = 5 + self.assertEqual(t[i], 5) +if __name__ == '__main__': + unittest.main() diff --git a/unit_tests/data/Test_TensorImpl.cpp b/unit_tests/data/Test_TensorImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cfcfb45e3735538c1650cfd990ea85e2333916ad --- /dev/null +++ b/unit_tests/data/Test_TensorImpl.cpp @@ -0,0 +1,100 @@ +/******************************************************************************** + * Copyright (c) 2023 CEA-List + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + ********************************************************************************/ + +#include <array> + +#include <catch2/catch_test_macros.hpp> + +#include "aidge/data/Tensor.hpp" +#include "aidge/utils/TensorUtils.hpp" +#include "aidge/backend/cpu/data/TensorImpl.hpp" + +using namespace Aidge; + +TEST_CASE("Tensor creation") { + SECTION("from const array") { + Tensor x = Array3D<int, 2, 2, 2>{{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}}; + + Tensor xCopy = Array3D<int, 2, 2, 2>{{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}}; + + Tensor xFloat = + Array3D<float, 2, 2, 2>{{{{1., 2.}, {3., 4.}}, {{5., 6.}, {7., 8.}}}}; + + SECTION("Tensor features") { + REQUIRE(x.nbDims() == 3); + REQUIRE(x.dims()[0] == 2); + REQUIRE(x.dims()[1] == 2); + REQUIRE(x.dims()[2] == 2); + REQUIRE(x.size() == 8); + } + + SECTION("Access to array") { + REQUIRE(static_cast<int *>(x.getImpl()->rawPtr())[0] == 1); + REQUIRE(static_cast<int *>(x.getImpl()->rawPtr())[7] == 8); + } + + SECTION("get function") { + REQUIRE(x.get<int>({0, 0, 0}) == 1); + REQUIRE(x.get<int>({0, 0, 1}) == 2); + REQUIRE(x.get<int>({0, 1, 1}) == 4); + REQUIRE(x.get<int>({1, 1, 0}) == 7); + x.set<int>({1, 1, 1}, 36); + REQUIRE(x.get<int>({1, 1, 1}) == 36); + } + + SECTION("Pretty printing for debug") { REQUIRE_NOTHROW(x.print()); } + + SECTION("Tensor (in)equality") { + REQUIRE(x == xCopy); + REQUIRE_FALSE(x == xFloat); + } + } +} + +TEST_CASE("Tensor methods") { + Tensor x = Array3D<int, 2, 2, 2>{{ + {{1, 2}, + {3, 4}}, + {{5, 6}, + {7, 8}} + }}; + + Tensor xCopy = Array3D<int, 2, 2, 2>{{{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}}; + + Tensor xFloat = + Array3D<float, 2, 2, 2>{{{{1., 2.}, {3., 4.}}, {{5., 6.}, {7., 8.}}}}; + + SECTION("Tensor sharing") { + Tensor xCopyCtor(x); + REQUIRE(xCopyCtor.getImpl() == x.getImpl()); + + Tensor xEqOp = x; + REQUIRE(xEqOp.getImpl() == x.getImpl()); + + Tensor xCloned = x.clone(); + REQUIRE(xCloned.getImpl() != x.getImpl()); + REQUIRE(xCloned == x); + } + + SECTION("Tensor extract") { + Tensor y = x.extract({0, 1}); + REQUIRE(y.getImpl() == x.getImpl()); + REQUIRE(approxEq<int>(y, Array1D<int, 2>{{3, 4}})); + REQUIRE(y.isContiguous()); + + Tensor y2 = x.extract({0, 1, 1}, {2, 1, 1}); + REQUIRE(y2.getImpl() == x.getImpl()); + REQUIRE(!y2.isContiguous()); + Tensor y3 = y2.clone(); + REQUIRE(y3.isContiguous()); + REQUIRE(approxEq<int>(y3, Array3D<int, 2, 1, 1>{{{{4}}, {{8}}}})); + } +}