From 35ef456e793ab30a13b475250d7a6c9e77880226 Mon Sep 17 00:00:00 2001 From: Fran Algaba Date: Mon, 22 May 2023 17:30:18 +0200 Subject: [PATCH 001/126] Sync main (#61) * Update SUMMARY.md * Update SUMMARY.md * update readme titles --------- Co-authored-by: raphaelDkhn <113879115+raphaelDkhn@users.noreply.github.com> Co-authored-by: raphaelDkhn --- README.md | 2 +- docs/README.md | 2 +- docs/SUMMARY.md | 21 ++++++++++++--------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 9d2bcd9fd..5aa78ec38 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ -# Orion: a library for Validity ML in Cairo 1.0 :sparkles: +# Orion: Cairo library for Validity ML ✨ [![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-) diff --git a/docs/README.md b/docs/README.md index 1adad7bd5..b9983f56e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -# Orion +# Orion: Cairo library for Validity ML ✨ Orion is a Cairo library that provides two high-level features: diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 19b451cec..c03bad9f8 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -11,7 +11,7 @@ * [Compatibility](apis/compatibility.md) * [Operators](apis/operators/README.md) * [Tensor](apis/operators/tensor/README.md) - * [TensorTrait::new](apis/operators/tensor/tensortrait-new.md) + * [tensor.new](apis/operators/tensor/tensortrait.new.md) * [tensor.at](apis/operators/tensor/tensor.at.md) * [tensor.min](apis/operators/tensor/tensor.min.md) * [tensor.max](apis/operators/tensor/tensor.max.md) @@ -25,20 +25,23 @@ * [tensor.matmul](apis/operators/tensor/tensor.matmul.md) * [tensor.exp](apis/operators/tensor/tensor.exp.md) * [Neural Network](apis/operators/neural-network/README.md) - * [NN::relu](apis/operators/neural-network/nn-relu.md) - * [NN::softmax](apis/operators/neural-network/nn-softmax.md) + * [nn.relu](apis/operators/neural-network/nn.relu.md) + * [nn.leaky_relu](apis/operators/neural-network/nn.leaky_relu.md) + * [nn.softmax](apis/operators/neural-network/nn.softmax.md) + * [nn.linear](apis/operators/neural-network/nn.linear.md) + * [Numbers](apis/numbers/README.md) * [Signed Integer](apis/numbers/signed-integer/README.md) - * [IntegerTrait::new](apis/numbers/signed-integer/integertrait-new.md) + * [int.new](apis/numbers/signed-integer/int.new.md) * [int.div\_rem](apis/numbers/signed-integer/int.div\_rem.md) * [int.abs](apis/numbers/signed-integer/int.abs.md) * [int.max](apis/numbers/signed-integer/int.max.md) * [int.min](apis/numbers/signed-integer/int.min.md) * [Fixed Point](apis/numbers/fixed-point/README.md) - * [Fixed::new](apis/numbers/fixed-point/fixed-new.md) - * [Fixed::new\_unscaled](apis/numbers/fixed-point/fixed-new\_unscaled.md) - * [Fixed::from\_felt](apis/numbers/fixed-point/fixed-from\_felt.md) - * [Fixed::from\_unscaled\_felt](apis/numbers/fixed-point/fixed-from\_unscaled\_felt.md) + * [fp.new](apis/numbers/fixed-point/fp.new.md) + * [fp.new\_unscaled](apis/numbers/fixed-point/fp.new_unscaled.md) + * [fp.from\_felt](apis/numbers/fixed-point/fp.from_felt.md) + * [fp.from\_unscaled\_felt](apis/numbers/fixed-point/fp.from_unscaled_felt.md) * [fp.abs](apis/numbers/fixed-point/fp.abs.md) * [fp.ceil](apis/numbers/fixed-point/fp.ceil.md) * [fp.floor](apis/numbers/fixed-point/fp.floor.md) @@ -51,7 +54,7 @@ * [fp.round](apis/numbers/fixed-point/fp.round.md) * [fp.sqrt](apis/numbers/fixed-point/fp.sqrt.md) * [Performance](apis/performance/README.md) - * [Linear Quantization](apis/performance/linear-quantization.md) + * [Linear Quantization](apis/performance/performance.quantize_linear.md) ## 💖 Community From f28d58bb6d2bdc36cfd9ee6af95ccedfcb7dd779 Mon Sep 17 00:00:00 2001 From: Fran Algaba Date: Mon, 22 May 2023 15:37:57 +0000 Subject: [PATCH 002/126] GITBOOK-9: Fix NN Table References --- docs/README.md | 8 ++- docs/SUMMARY.md | 13 ++-- docs/apis/operators/tensor/tensor.new.md | 80 +----------------------- 3 files changed, 13 insertions(+), 88 deletions(-) diff --git a/docs/README.md b/docs/README.md index b9983f56e..ac1b6d012 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,8 @@ -# Orion: Cairo library for Validity ML ✨ +--- +description: ONNX Runtime in Cairo 1.0 +--- + +# Orion Orion is a Cairo library that provides two high-level features: @@ -15,7 +19,7 @@ This library proposes a new ONNX runtime built with [Cairo](https://www.cairo-la ### 🌱 Where to start? -
🧱 APIsThree APIs that will help you to build your Validity ML models.get-started.md
🧩 AlgorithmsDiscover all algorithms built by the community, or build your own. algorithms.md
📖 TutorialsTry out the awesome guides and tutorials created by the community.tutorials.md
+
🧱 APIsThree APIs that will help you to build your Validity ML models.get-started.md
🧩 AlgorithmsDiscover all algorithms built by the community, or build your own.algorithms.md
📖 TutorialsTry out the awesome guides and tutorials created by the community.tutorials.md
### ✨ What's new? diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index c03bad9f8..cd1e1c7d7 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -11,7 +11,7 @@ * [Compatibility](apis/compatibility.md) * [Operators](apis/operators/README.md) * [Tensor](apis/operators/tensor/README.md) - * [tensor.new](apis/operators/tensor/tensortrait.new.md) + * [tensor.new](apis/operators/tensor/tensor.new.md) * [tensor.at](apis/operators/tensor/tensor.at.md) * [tensor.min](apis/operators/tensor/tensor.min.md) * [tensor.max](apis/operators/tensor/tensor.max.md) @@ -26,10 +26,9 @@ * [tensor.exp](apis/operators/tensor/tensor.exp.md) * [Neural Network](apis/operators/neural-network/README.md) * [nn.relu](apis/operators/neural-network/nn.relu.md) - * [nn.leaky_relu](apis/operators/neural-network/nn.leaky_relu.md) + * [nn.leaky\_relu](apis/operators/neural-network/nn.leaky\_relu.md) * [nn.softmax](apis/operators/neural-network/nn.softmax.md) * [nn.linear](apis/operators/neural-network/nn.linear.md) - * [Numbers](apis/numbers/README.md) * [Signed Integer](apis/numbers/signed-integer/README.md) * [int.new](apis/numbers/signed-integer/int.new.md) @@ -39,9 +38,9 @@ * [int.min](apis/numbers/signed-integer/int.min.md) * [Fixed Point](apis/numbers/fixed-point/README.md) * [fp.new](apis/numbers/fixed-point/fp.new.md) - * [fp.new\_unscaled](apis/numbers/fixed-point/fp.new_unscaled.md) - * [fp.from\_felt](apis/numbers/fixed-point/fp.from_felt.md) - * [fp.from\_unscaled\_felt](apis/numbers/fixed-point/fp.from_unscaled_felt.md) + * [fp.new\_unscaled](apis/numbers/fixed-point/fp.new\_unscaled.md) + * [fp.from\_felt](apis/numbers/fixed-point/fp.from\_felt.md) + * [fp.from\_unscaled\_felt](apis/numbers/fixed-point/fp.from\_unscaled\_felt.md) * [fp.abs](apis/numbers/fixed-point/fp.abs.md) * [fp.ceil](apis/numbers/fixed-point/fp.ceil.md) * [fp.floor](apis/numbers/fixed-point/fp.floor.md) @@ -54,7 +53,7 @@ * [fp.round](apis/numbers/fixed-point/fp.round.md) * [fp.sqrt](apis/numbers/fixed-point/fp.sqrt.md) * [Performance](apis/performance/README.md) - * [Linear Quantization](apis/performance/performance.quantize_linear.md) + * [Linear Quantization](apis/performance/performance.quantize\_linear.md) ## 💖 Community diff --git a/docs/apis/operators/tensor/tensor.new.md b/docs/apis/operators/tensor/tensor.new.md index 18a3fcea4..9e5af0ee2 100644 --- a/docs/apis/operators/tensor/tensor.new.md +++ b/docs/apis/operators/tensor/tensor.new.md @@ -1,80 +1,2 @@ -# TensorTrait::new +# tensor.new -```rust -fn new(shape: Span, data: Span) -> Tensor; -``` - -Returns a new tensor with the given shape and data. - -## Args - -* `shape`(`Span`) - A span representing the shape of the tensor. -* `data` (`Span`) - A span containing the array of elements. - -## Panics - -* Panics if the shape and data length are incompatible. - -## Returns - -A new `Tensor` instance. - -## Examples - -Let's create new u32 Tensors. - -```rust -// 1D TENSOR -fn tensor_1D() -> Tensor { -let mut shape = ArrayTrait::new(); -shape.append(3); - -let mut data = ArrayTrait::new(); -data.append(0_u32); -data.append(1_u32); -data.append(2_u32); - -let tensor = TensorTrait::::new(shape.span(), data.span()); - -return tensor; -} - -// 2D TENSOR -fn tensor_2D() -> Tensor { -let mut shape = ArrayTrait::new(); -shape.append(2); -shape.append(2); - -let mut data = ArrayTrait::new(); -data.append(0_u32); -data.append(1_u32); -data.append(2_u32); -data.append(3_u32); - -let tensor = TensorTrait::::new(shape.span(), data.span()); - -return tensor; -} - -// 3D TENSOR -fn tensor_3D() -> Tensor { -let mut shape = ArrayTrait::new(); -shape.append(2); -shape.append(2); -shape.append(2); - -let mut data = ArrayTrait::new(); -data.append(0_u32); -data.append(1_u32); -data.append(2_u32); -data.append(3_u32); -data.append(4_u32); -data.append(5_u32); -data.append(6_u32); -data.append(7_u32); - -let tensor = TensorTrait::::new(shape.span(), data.span()); - -return tensor; -} -``` From f57a2e872bb3c61f007b99de5a9e9565d92e1911 Mon Sep 17 00:00:00 2001 From: Fran Algaba Date: Mon, 22 May 2023 17:43:56 +0200 Subject: [PATCH 003/126] Fix markdown content (#62) --- docs/apis/operators/tensor/tensor.new.md | 78 ++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/docs/apis/operators/tensor/tensor.new.md b/docs/apis/operators/tensor/tensor.new.md index 9e5af0ee2..988364f69 100644 --- a/docs/apis/operators/tensor/tensor.new.md +++ b/docs/apis/operators/tensor/tensor.new.md @@ -1,2 +1,80 @@ # tensor.new +```rust +fn new(shape: Span, data: Span) -> Tensor; +``` + +Returns a new tensor with the given shape and data. + +## Args + +* `shape`(`Span`) - A span representing the shape of the tensor. +* `data` (`Span`) - A span containing the array of elements. + +## Panics + +* Panics if the shape and data length are incompatible. + +## Returns + +A new `Tensor` instance. + +## Examples + +Let's create new u32 Tensors. + +```rust +// 1D TENSOR +fn tensor_1D() -> Tensor { +let mut shape = ArrayTrait::new(); +shape.append(3); + +let mut data = ArrayTrait::new(); +data.append(0_u32); +data.append(1_u32); +data.append(2_u32); + +let tensor = TensorTrait::::new(shape.span(), data.span()); + +return tensor; +} + +// 2D TENSOR +fn tensor_2D() -> Tensor { +let mut shape = ArrayTrait::new(); +shape.append(2); +shape.append(2); + +let mut data = ArrayTrait::new(); +data.append(0_u32); +data.append(1_u32); +data.append(2_u32); +data.append(3_u32); + +let tensor = TensorTrait::::new(shape.span(), data.span()); + +return tensor; +} + +// 3D TENSOR +fn tensor_3D() -> Tensor { +let mut shape = ArrayTrait::new(); +shape.append(2); +shape.append(2); +shape.append(2); + +let mut data = ArrayTrait::new(); +data.append(0_u32); +data.append(1_u32); +data.append(2_u32); +data.append(3_u32); +data.append(4_u32); +data.append(5_u32); +data.append(6_u32); +data.append(7_u32); + +let tensor = TensorTrait::::new(shape.span(), data.span()); + +return tensor; +} +``` \ No newline at end of file From 031784d82e9ccb5b7ec8b241343672bae374d8df Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Sun, 18 Jun 2023 09:30:10 +0300 Subject: [PATCH 004/126] convert elements to felt252 in tests --- src/tests/operators/linalg/matmul_test.cairo | 22 +- .../operators/math/reduce_sum_test.cairo | 31 +- .../leaky_relu/leaky_relu_i32_test.cairo | 16 +- .../nn/functional/linear/linear_test.cairo | 15 +- .../logsoftmax/logsoftmax_test.cairo | 21 +- .../nn/functional/relu/relu_i32_test.cairo | 9 +- .../nn/functional/softmax/softmax_test.cairo | 18 +- .../softplus/softplus_i32_test.cairo | 24 +- .../softsign/softsign_i32_test.cairo | 20 +- src/tests/operators/tensor/tensor_test.cairo | 313 +++++++++--------- src/tests/performance/quantization_test.cairo | 47 +-- 11 files changed, 241 insertions(+), 295 deletions(-) diff --git a/src/tests/operators/linalg/matmul_test.cairo b/src/tests/operators/linalg/matmul_test.cairo index 52b8b6d50..65a52011f 100644 --- a/src/tests/operators/linalg/matmul_test.cairo +++ b/src/tests/operators/linalg/matmul_test.cairo @@ -16,7 +16,7 @@ fn tensor_matmul() { let tensor_2 = i32_tensor_1x3_helper(); let result = tensor_1.matmul(@tensor_2); - assert(*result.data.at(0).mag == 5, 'result[0] = 5'); + assert((*result.data[0]).into() == 5, 'result[0] = 5'); assert(result.data.len() == 1, 'data len is 1'); assert(result.shape.len() == 1, 'shape len is 1'); @@ -25,10 +25,10 @@ fn tensor_matmul() { let tensor_2 = i32_tensor_2x2_helper(); let result = tensor_1.matmul(@tensor_2); - assert(*result.data.at(0).mag == 2, 'result[0] = 2'); - assert(*result.data.at(1).mag == 3, 'result[1] = 3'); - assert(*result.data.at(2).mag == 6, 'result[2] = 6'); - assert(*result.data.at(3).mag == 11, 'result[3] = 11'); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 6, 'result[2] = 6'); + assert((*result.data[3]).into() == 11, 'result[3] = 11'); assert(result.data.len() == 4, 'data len is 4'); assert(result.shape.len() == 2, 'shape len is 2'); } @@ -41,9 +41,9 @@ fn tensor_matmul_with_matrix_vec() { let tensor_2 = i32_tensor_1x3_helper(); let result = tensor_1.matmul(@tensor_2); - assert(*result.data.at(0).mag == 5, 'result[0] = 5'); - assert(*result.data.at(1).mag == 14, 'result[1] = 14'); - assert(*result.data.at(2).mag == 23, 'result[2] = 23'); + assert((*result.data[0]).into() == 5, 'result[0] = 5'); + assert((*result.data[1]).into() == 14, 'result[1] = 14'); + assert((*result.data[2]).into() == 23, 'result[2] = 23'); assert(result.data.len() == 3, 'data len is 3'); assert(result.shape.len() == 1, 'shape len is 1'); @@ -52,9 +52,9 @@ fn tensor_matmul_with_matrix_vec() { let tensor_2 = i32_tensor_3x3_helper(); let result = tensor_1.matmul(@tensor_2); - assert(*result.data.at(0).mag == 15, 'result[0] = 15'); - assert(*result.data.at(1).mag == 18, 'result[1] = 18'); - assert(*result.data.at(2).mag == 21, 'result[2] = 21'); + assert((*result.data[0]).into() == 15, 'result[0] = 15'); + assert((*result.data[1]).into() == 18, 'result[1] = 18'); + assert((*result.data[2]).into() == 21, 'result[2] = 21'); assert(result.data.len() == 3, 'data len is 3'); assert(result.shape.len() == 1, 'shape len is 1'); } diff --git a/src/tests/operators/math/reduce_sum_test.cairo b/src/tests/operators/math/reduce_sum_test.cairo index d74059fa8..c163fed7b 100644 --- a/src/tests/operators/math/reduce_sum_test.cairo +++ b/src/tests/operators/math/reduce_sum_test.cairo @@ -1,8 +1,11 @@ use array::SpanTrait; +use traits::Into; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::TensorTrait; -use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_2x2x2_helper, i32_tensor_1x3_helper}; +use orion::tests::operators::tensor::helpers::helpers_i32::{ + i32_tensor_2x2x2_helper, i32_tensor_1x3_helper +}; use debug::PrintTrait; @@ -12,7 +15,7 @@ fn reduce_sum_1d() { let tensor = i32_tensor_1x3_helper(); let result = tensor.reduce_sum(0, false); - assert(*result.data.at(0).mag == 3, 'result[0] = 3'); + assert((*result.data[0]).into() == 3, 'result[0] = 3'); assert(result.data.len() == 1, 'result.len = 1'); } @@ -23,22 +26,22 @@ fn reduce_sum_3d() { let result = tensor.reduce_sum(0, false); - assert(*result.data.at(0).mag == 4_u32, 'result[0] = 4'); - assert(*result.data.at(1).mag == 6_u32, 'result[1] = 6'); - assert(*result.data.at(2).mag == 8_u32, 'result[2] = 8'); - assert(*result.data.at(3).mag == 10_u32, 'result[3] = 10'); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 6, 'result[1] = 6'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 10, 'result[3] = 10'); let result = tensor.reduce_sum(1, false).data; - assert(*result.at(0).mag == 2_u32, 'result[0] = 2'); - assert(*result.at(1).mag == 4_u32, 'result[1] = 4'); - assert(*result.at(2).mag == 10_u32, 'result[2] = 10'); - assert(*result.at(3).mag == 12_u32, 'result[3] = 12'); + assert((*result[0]).into() == 2, 'result[0] = 2'); + assert((*result[1]).into() == 4, 'result[1] = 4'); + assert((*result[2]).into() == 10, 'result[2] = 10'); + assert((*result[3]).into() == 12, 'result[3] = 12'); let result = tensor.reduce_sum(2, false).data; - assert(*result.at(0).mag == 1_u32, 'result[0] = 1'); - assert(*result.at(1).mag == 5_u32, 'result[1] = 5'); - assert(*result.at(2).mag == 9_u32, 'result[2] = 9'); - assert(*result.at(3).mag == 13_u32, 'result[3] = 13'); + assert((*result[0]).into() == 1, 'result[0] = 1'); + assert((*result[1]).into() == 5, 'result[1] = 5'); + assert((*result[2]).into() == 9, 'result[2] = 9'); + assert((*result[3]).into() == 13, 'result[3] = 13'); } diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo index 138e31129..972c1fd10 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo @@ -1,6 +1,7 @@ use core::option::OptionTrait; use array::ArrayTrait; use array::SpanTrait; +use traits::Into; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -8,7 +9,6 @@ use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::{NNTrait}; use orion::operators::nn::implementations::impl_nn_i32; use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; - use orion::numbers::fixed_point::implementations::impl_8x23; #[test] @@ -41,16 +41,8 @@ fn leaky_relu_i32_test() { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - let data_0 = *result.data.at(0); - assert(data_0.mag == impl_8x23::ONE, 'result[0] == 8388608'); // 1 - assert(data_0.sign == false, 'result[0].sign == false'); - - let data_3 = *result.data.at(3); - assert(data_3.mag == 1677722, 'result[3] == 1677722'); // 2 * 0.1 = 0.2 - assert(data_3.sign == true, 'result[3].sign == true'); - - let data_5 = *result.data.at(5); - assert(data_5.mag == 0, 'result[5] == 0'); - assert(data_5.sign == false, 'result[5].sign == false'); + assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 + assert((*result.data.at(3)).into() == - 1677722, 'result[3] == - 1677722'); // 2 * 0.1 = - 0.2 + assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); } diff --git a/src/tests/operators/nn/functional/linear/linear_test.cairo b/src/tests/operators/nn/functional/linear/linear_test.cairo index 7b6fc56d8..6b0ce5117 100644 --- a/src/tests/operators/nn/functional/linear/linear_test.cairo +++ b/src/tests/operators/nn/functional/linear/linear_test.cairo @@ -1,5 +1,6 @@ use array::ArrayTrait; use array::SpanTrait; +use traits::Into; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -46,17 +47,11 @@ fn linear_test() { // TEST UNQUANTIZED let result = NNTrait::linear(inputs, weights, bias, false).data; - assert( - *result.at(0_usize).mag == 5541_u32 & *result.at(0_usize).sign == false, 'result[0] = 5541' - ); - assert( - *result.at(1_usize).mag == 260_u32 & *result.at(1_usize).sign == true, 'result[1] = -260' - ); + assert((*result[0]).into() == 5541, 'result[0] = 5541'); + assert((*result[1]).into() == -260, 'result[1] = -260'); // TEST QUANTIZED let result = NNTrait::linear(inputs, weights, bias, true).data; - assert( - *result.at(0_usize).mag == 127_u32 & *result.at(0_usize).sign == false, 'result[0] = 127' - ); - assert(*result.at(1_usize).mag == 6_u32 & *result.at(1_usize).sign == true, 'result[1] = -6'); + assert((*result[0]).into() == 127, 'result[0] = 127'); + assert((*result[1]).into() == -6, 'result[1] = -6'); } diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo index 4b566a42a..7510c7278 100644 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo @@ -1,16 +1,13 @@ use array::SpanTrait; - use traits::Into; use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; +use orion::numbers::fixed_point::implementations::impl_8x23; use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32; -use debug::PrintTrait; - -use debug::print_felt252; #[test] #[available_gas(20000000)] @@ -21,15 +18,15 @@ fn logsoftmax_test() { let mut result = NNTrait::logsoftmax(@tensor, 0).data; - assert(*result.at(0).mag == 17841970, 'result[0] = -2.12693'); - assert(*result.at(1).mag == 17841970, 'result[1] = -2.12695'); - assert(*result.at(2).mag == 1064751, 'result[2] = -0.12692'); - assert(*result.at(3).mag == 1064751, 'result[3] = -0.12692'); + assert((*result[0]).into() == -17841970, 'result[0] = -2.12693'); + assert((*result[1]).into() == -17841970, 'result[1] = -2.12695'); + assert((*result[2]).into() == -1064751, 'result[2] = -0.12692'); + assert((*result[3]).into() == -1064751, 'result[3] = -0.12692'); let mut result = NNTrait::logsoftmax(@tensor, 1).data; - assert(*result.at(0).mag == 11016451, 'result[0] = -1.3134'); - assert(*result.at(1).mag == 2627827, 'result[1] = -0.3132'); - assert(*result.at(2).mag == 11016460, 'result[2] = -1.3134'); - assert(*result.at(3).mag == 2627829, 'result[3] = -0.3132'); + assert((*result.at(0)).into() == -11016451, 'result[0] = -1.3134'); + assert((*result.at(1)).into() == -2627827, 'result[1] = -0.3132'); + assert((*result.at(2)).into() == -11016460, 'result[2] = -1.3134'); + assert((*result.at(3)).into() == -2627829, 'result[3] = -0.3132'); } diff --git a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo index fc1909e26..d70ff1e7c 100644 --- a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo @@ -1,5 +1,6 @@ use array::ArrayTrait; use array::SpanTrait; +use traits::Into; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -33,10 +34,6 @@ fn relu_i32_test() { let mut result = NNTrait::relu(@tensor, threshold); let data_0 = *result.data.at(0); - assert(data_0.mag == 1_u32, 'result[0] == 1'); - assert(data_0.sign == false, 'result[0] == 1'); - - let data_3 = *result.data.at(3); - assert(data_3.mag == 0_u32, 'result[3] == 0'); - assert(data_3.sign == false, 'result[3] == 0'); + assert((*result.data.at(0)).into() == 1, 'result[0] == 1'); + assert((*result.data.at(3)).into() == 0, 'result[3] == 0'); } diff --git a/src/tests/operators/nn/functional/softmax/softmax_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_test.cairo index e98ff4a03..3716cee06 100644 --- a/src/tests/operators/nn/functional/softmax/softmax_test.cairo +++ b/src/tests/operators/nn/functional/softmax/softmax_test.cairo @@ -1,11 +1,11 @@ use array::SpanTrait; - use traits::Into; use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; +use orion::numbers::fixed_point::implementations::impl_8x23; use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32; @@ -20,15 +20,15 @@ fn softmax_test() { let mut result = NNTrait::softmax(@tensor, 0).data; - assert(*result.at(0).mag == 999946, 'result[0] = 0.1192'); - assert(*result.at(1).mag == 999946, 'result[1] = 0.1192'); - assert(*result.at(2).mag == 7388661, 'result[2] = 0.8808'); - assert(*result.at(3).mag == 7388661, 'result[3] = 0.8808'); + assert((*result.at(0)).into() == 999946, 'result[0] = 0.1192'); + assert((*result.at(1)).into() == 999946, 'result[1] = 0.1192'); + assert((*result.at(2)).into() == 7388661, 'result[2] = 0.8808'); + assert((*result.at(3)).into() == 7388661, 'result[3] = 0.8808'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert(*result.at(0).mag == 2256044, 'result[0] = 0.2689'); - assert(*result.at(1).mag == 6132563, 'result[1] = 0.7311'); - assert(*result.at(2).mag == 2256043, 'result[2] = 0.2689'); - assert(*result.at(3).mag == 6132564, 'result[4] = 0.7311'); + assert((*result.at(0)).into() == 2256044, 'result[0] = 0.2689'); + assert((*result.at(1)).into() == 6132563, 'result[1] = 0.7311'); + assert((*result.at(2)).into() == 2256043, 'result[2] = 0.2689'); + assert((*result.at(3)).into() == 6132564, 'result[4] = 0.7311'); } diff --git a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo index 50797d98c..03260cc5e 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo @@ -1,6 +1,7 @@ use core::option::OptionTrait; use array::ArrayTrait; use array::SpanTrait; +use traits::Into; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -8,10 +9,10 @@ use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32; use orion::numbers::fixed_point::core::FixedImpl; - +use orion::numbers::fixed_point::implementations::impl_8x23; #[test] -#[available_gas(5000000)] +#[available_gas(50000000)] fn softplus_i32_test() { let mut shape = ArrayTrait::::new(); shape.append(2); @@ -33,20 +34,9 @@ fn softplus_i32_test() { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - let data_0 = *result.data.at(0); - assert(data_0.mag == 5814556, 'result[0] == 5814556'); // 0.6931452 - assert(data_0.sign == false, 'result[0].sign == false'); - - let data_1 = *result.data.at(1); - assert(data_1.mag == 11016447, 'result[1] == 11016447'); // 1.31326096 - assert(data_1.sign == false, 'result[1].sign == false'); - - let data_2 = *result.data.at(2); - assert(data_2.mag == 1064751, 'result[2] == 1064751'); // 0.12692797 - assert(data_2.sign == false, 'result[2].sign == false'); - - let data_3 = *result.data.at(3); - assert(data_3.mag == 407580, 'result[3] == 407580'); // 0.04858729 - assert(data_3.sign == false, 'result[3].sign == false'); + assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data.at(2)).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 + assert((*result.data.at(3)).into() == 407580, 'result[3] == 407580'); // 0.04858729 } diff --git a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo index 7de4417c2..70a54dc99 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo @@ -1,6 +1,7 @@ use core::option::OptionTrait; use array::ArrayTrait; use array::SpanTrait; +use traits::Into; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -8,6 +9,7 @@ use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32; use orion::numbers::fixed_point::core::FixedImpl; +use orion::numbers::fixed_point::implementations::impl_8x23; #[test] #[available_gas(2000000)] @@ -33,19 +35,9 @@ fn softsign_i32_test() { let mut result = NNTrait::softsign(@tensor); let data = *result.data.at(0); - assert(data.mag == 0, 'result[0] == 0'); // 0 - assert(data.sign == false, 'result[0].sign == false'); - - let data = *result.data.at(1); - assert(data.mag == 4194304, 'result[1] == 4194304'); // 0.5 - assert(data.sign == false, 'result[1].sign == false'); - - let data = *result.data.at(2); - assert(data.mag == 5592405, 'result[2] == 5592405'); // -0.67 - assert(data.sign == true, 'result[2].sign == true'); - - let data = *result.data.at(3); - assert(data.mag == 6291456, 'result[3] == 6291456'); // -0.75 - assert(data.sign == true, 'result[3].sign == true'); + assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data.at(1)).into() == 4194304, 'result[1] == 4194304'); // 0.5 + assert((*result.data.at(2)).into() == -5592405, 'result[2] == 5592405'); // -0.67 + assert((*result.data.at(3)).into() == -6291456, 'result[3] == 6291456'); // -0.75 } diff --git a/src/tests/operators/tensor/tensor_test.cairo b/src/tests/operators/tensor/tensor_test.cairo index 737d7076b..3e4390b4e 100644 --- a/src/tests/operators/tensor/tensor_test.cairo +++ b/src/tests/operators/tensor/tensor_test.cairo @@ -1,5 +1,6 @@ use array::ArrayTrait; use array::SpanTrait; +use traits::Into; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -149,14 +150,14 @@ fn add_tensor() { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 2_u32, 'result[1] = 2'); - assert(*result.at(2).mag == 4_u32, 'result[2] = 4'); - assert(*result.at(3).mag == 6_u32, 'result[3] = 6'); - assert(*result.at(4).mag == 8_u32, 'result[4] = 8'); - assert(*result.at(5).mag == 10_u32, 'result[5] = 10'); - assert(*result.at(6).mag == 12_u32, 'result[6] = 12'); - assert(*result.at(7).mag == 14_u32, 'result[7] = 14'); + assert((*result[0]).into() == 0, 'result[0] = 0'); + assert((*result[1]).into() == 2, 'result[1] = 2'); + assert((*result[2]).into() == 4, 'result[2] = 4'); + assert((*result[3]).into() == 6, 'result[3] = 6'); + assert((*result[4]).into() == 8, 'result[4] = 8'); + assert((*result[5]).into() == 10, 'result[5] = 10'); + assert((*result[6]).into() == 12, 'result[6] = 12'); + assert((*result[7]).into() == 14, 'result[7] = 14'); // broadcast operation @@ -172,14 +173,14 @@ fn add_tensor() { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0).mag == 10_u32, 'result[0] = 10'); - assert(*result.at(1).mag == 11_u32, 'result[1] = 11'); - assert(*result.at(2).mag == 102_u32, 'result[2] = 102'); - assert(*result.at(3).mag == 103_u32, 'result[3] = 103'); - assert(*result.at(4).mag == 14_u32, 'result[4] = 14'); - assert(*result.at(5).mag == 15_u32, 'result[5] = 15'); - assert(*result.at(6).mag == 106_u32, 'result[6] = 106'); - assert(*result.at(7).mag == 107_u32, 'result[7] = 107'); + assert((*result[0]).into() == 10, 'result[0] = 10'); + assert((*result[1]).into() == 11, 'result[1] = 11'); + assert((*result[2]).into() == 102, 'result[2] = 102'); + assert((*result[3]).into() == 103, 'result[3] = 103'); + assert((*result[4]).into() == 14, 'result[4] = 14'); + assert((*result[5]).into() == 15, 'result[5] = 15'); + assert((*result[6]).into() == 106, 'result[6] = 106'); + assert((*result[7]).into() == 107, 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -193,14 +194,14 @@ fn add_tensor() { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0).mag == 10_u32, 'result[0] = 10'); - assert(*result.at(1).mag == 11_u32, 'result[1] = 11'); - assert(*result.at(2).mag == 12_u32, 'result[2] = 12'); - assert(*result.at(3).mag == 13_u32, 'result[3] = 13'); - assert(*result.at(4).mag == 104_u32, 'result[4] = 104'); - assert(*result.at(5).mag == 105_u32, 'result[5] = 105'); - assert(*result.at(6).mag == 106_u32, 'result[6] = 106'); - assert(*result.at(7).mag == 107_u32, 'result[7] = 107'); + assert((*result[0]).into() == 10, 'result[0] = 10'); + assert((*result[1]).into() == 11, 'result[1] = 11'); + assert((*result[2]).into() == 12, 'result[2] = 12'); + assert((*result[3]).into() == 13, 'result[3] = 13'); + assert((*result[4]).into() == 104, 'result[4] = 104'); + assert((*result[5]).into() == 105, 'result[5] = 105'); + assert((*result[6]).into() == 106, 'result[6] = 106'); + assert((*result[7]).into() == 107, 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(1); @@ -214,14 +215,14 @@ fn add_tensor() { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0).mag == 10_u32, 'result[0] = 10'); - assert(*result.at(1).mag == 101_u32, 'result[1] = 101'); - assert(*result.at(2).mag == 12_u32, 'result[2] = 12'); - assert(*result.at(3).mag == 103_u32, 'result[3] = 103'); - assert(*result.at(4).mag == 14_u32, 'result[4] = 14'); - assert(*result.at(5).mag == 105_u32, 'result[5] = 105'); - assert(*result.at(6).mag == 16_u32, 'result[6] = 16'); - assert(*result.at(7).mag == 107_u32, 'result[7] = 107'); + assert((*result[0]).into() == 10, 'result[0] = 10'); + assert((*result[1]).into() == 101, 'result[1] = 101'); + assert((*result[2]).into() == 12, 'result[2] = 12'); + assert((*result[3]).into() == 103, 'result[3] = 103'); + assert((*result[4]).into() == 14, 'result[4] = 14'); + assert((*result[5]).into() == 105, 'result[5] = 105'); + assert((*result[6]).into() == 16, 'result[6] = 16'); + assert((*result[7]).into() == 107, 'result[7] = 107'); } #[test] @@ -232,14 +233,14 @@ fn sub_tensor() { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 0_u32, 'result[1] = 0'); - assert(*result.at(2).mag == 0_u32, 'result[2] = 0'); - assert(*result.at(3).mag == 0_u32, 'result[3] = 0'); - assert(*result.at(4).mag == 0_u32, 'result[4] = 0'); - assert(*result.at(5).mag == 0_u32, 'result[5] = 0'); - assert(*result.at(6).mag == 0_u32, 'result[6] = 0'); - assert(*result.at(7).mag == 0_u32, 'result[7] = 0'); + assert((*result[0]).into() == 0, 'result[0] = 0'); + assert((*result[1]).into() == 0, 'result[1] = 0'); + assert((*result[2]).into() == 0, 'result[2] = 0'); + assert((*result[3]).into() == 0, 'result[3] = 0'); + assert((*result[4]).into() == 0, 'result[4] = 0'); + assert((*result[5]).into() == 0, 'result[5] = 0'); + assert((*result[6]).into() == 0, 'result[6] = 0'); + assert((*result[7]).into() == 0, 'result[7] = 0'); // broadcast operation @@ -255,14 +256,14 @@ fn sub_tensor() { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 1_u32, 'result[1] = 1'); - assert(*result.at(2).mag == 1_u32, 'result[2] = 1'); - assert(*result.at(3).mag == 2_u32, 'result[3] = 2'); - assert(*result.at(4).mag == 4_u32, 'result[4] = 4'); - assert(*result.at(5).mag == 5_u32, 'result[5] = 5'); - assert(*result.at(6).mag == 5_u32, 'result[6] = 5'); - assert(*result.at(7).mag == 6_u32, 'result[7] = 6'); + assert((*result[0]).into() == 0, 'result[0] = 0'); + assert((*result[1]).into() == 1, 'result[1] = 1'); + assert((*result[2]).into() == 1, 'result[2] = 1'); + assert((*result[3]).into() == 2, 'result[3] = 2'); + assert((*result[4]).into() == 4, 'result[4] = 4'); + assert((*result[5]).into() == 5, 'result[5] = 5'); + assert((*result[6]).into() == 5, 'result[6] = 5'); + assert((*result[7]).into() == 6, 'result[7] = 6'); } #[test] @@ -273,14 +274,14 @@ fn mul_tensor() { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 1_u32, 'result[1] = 1'); - assert(*result.at(2).mag == 4_u32, 'result[2] = 4'); - assert(*result.at(3).mag == 9_u32, 'result[3] = 9'); - assert(*result.at(4).mag == 16_u32, 'result[4] = 16'); - assert(*result.at(5).mag == 25_u32, 'result[5] = 25'); - assert(*result.at(6).mag == 36_u32, 'result[6] = 36'); - assert(*result.at(7).mag == 49_u32, 'result[7] = 49'); + assert((*result[0]).into() == 0, 'result[0] = 0'); + assert((*result[1]).into() == 1, 'result[1] = 1'); + assert((*result[2]).into() == 4, 'result[2] = 4'); + assert((*result[3]).into() == 9, 'result[3] = 9'); + assert((*result[4]).into() == 16, 'result[4] = 16'); + assert((*result[5]).into() == 25, 'result[5] = 25'); + assert((*result[6]).into() == 36, 'result[6] = 36'); + assert((*result[7]).into() == 49, 'result[7] = 49'); // broadcast operation @@ -296,14 +297,14 @@ fn mul_tensor() { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 10_u32, 'result[1] = 10'); - assert(*result.at(2).mag == 200_u32, 'result[2] = 200'); - assert(*result.at(3).mag == 300_u32, 'result[3] = 300'); - assert(*result.at(4).mag == 40_u32, 'result[4] = 40'); - assert(*result.at(5).mag == 50_u32, 'result[5] = 50'); - assert(*result.at(6).mag == 600_u32, 'result[6] = 600'); - assert(*result.at(7).mag == 700_u32, 'result[7] = 700'); + assert((*result[0]).into() == 0, 'result[0] = 0'); + assert((*result[1]).into() == 10, 'result[1] = 10'); + assert((*result[2]).into() == 200, 'result[2] = 200'); + assert((*result[3]).into() == 300, 'result[3] = 300'); + assert((*result[4]).into() == 40, 'result[4] = 40'); + assert((*result[5]).into() == 50, 'result[5] = 50'); + assert((*result[6]).into() == 600, 'result[6] = 600'); + assert((*result[7]).into() == 700, 'result[7] = 700'); } #[test] @@ -343,14 +344,14 @@ fn div_tensor() { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0).mag == 1_u32, 'result[0] = 1'); - assert(*result.at(1).mag == 1_u32, 'result[1] = 1'); - assert(*result.at(2).mag == 1_u32, 'result[2] = 1'); - assert(*result.at(3).mag == 1_u32, 'result[3] = 1'); - assert(*result.at(4).mag == 1_u32, 'result[4] = 1'); - assert(*result.at(5).mag == 1_u32, 'result[5] = 1'); - assert(*result.at(6).mag == 1_u32, 'result[6] = 1'); - assert(*result.at(7).mag == 1_u32, 'result[7] = 1'); + assert((*result[0]).into() == 1, 'result[0] = 1'); + assert((*result[1]).into() == 1, 'result[1] = 1'); + assert((*result[2]).into() == 1, 'result[2] = 1'); + assert((*result[3]).into() == 1, 'result[3] = 1'); + assert((*result[4]).into() == 1, 'result[4] = 1'); + assert((*result[5]).into() == 1, 'result[5] = 1'); + assert((*result[6]).into() == 1, 'result[6] = 1'); + assert((*result[7]).into() == 1, 'result[7] = 1'); // broadcast operation @@ -366,14 +367,14 @@ fn div_tensor() { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0).mag == 10_u32, 'result[0] = 10'); - assert(*result.at(1).mag == 20_u32, 'result[1] = 20'); - assert(*result.at(2).mag == 3_u32, 'result[2] = 3'); - assert(*result.at(3).mag == 4_u32, 'result[3] = 4'); - assert(*result.at(4).mag == 50_u32, 'result[4] = 50'); - assert(*result.at(5).mag == 60_u32, 'result[5] = 60'); - assert(*result.at(6).mag == 7_u32, 'result[6] = 7'); - assert(*result.at(7).mag == 8_u32, 'result[7] = 8'); + assert((*result[0]).into() == 10, 'result[0] = 10'); + assert((*result[1]).into() == 20, 'result[1] = 20'); + assert((*result[2]).into() == 3, 'result[2] = 3'); + assert((*result[3]).into() == 4, 'result[3] = 4'); + assert((*result[4]).into() == 50, 'result[4] = 50'); + assert((*result[5]).into() == 60, 'result[5] = 60'); + assert((*result[6]).into() == 7, 'result[6] = 7'); + assert((*result[7]).into() == 8, 'result[7] = 8'); } #[test] @@ -387,10 +388,10 @@ fn tensor_transpose_2D() { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0).mag == 0, 'result[0] = 0'); - assert(*result.data.at(1).mag == 2, 'result[1] = 2'); - assert(*result.data.at(2).mag == 1, 'result[2] = 1'); - assert(*result.data.at(3).mag == 3, 'result[3] = 3'); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 2, 'result[1] = 2'); + assert((*result.data[2]).into() == 1, 'result[2] = 1'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); assert(*result.shape.at(0) == 2, 'shape[0] = 2'); assert(*result.shape.at(1) == 2, 'shape[1] = 2'); @@ -398,12 +399,12 @@ fn tensor_transpose_2D() { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0).mag == 0, 'result[0] = 0'); - assert(*result.data.at(1).mag == 2, 'result[1] = 2'); - assert(*result.data.at(2).mag == 4, 'result[2] = 4'); - assert(*result.data.at(3).mag == 1, 'result[3] = 1'); - assert(*result.data.at(4).mag == 3, 'result[4] = 3'); - assert(*result.data.at(5).mag == 5, 'result[5] = 5'); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 2, 'result[1] = 2'); + assert((*result.data[2]).into() == 4, 'result[2] = 4'); + assert((*result.data[3]).into() == 1, 'result[3] = 1'); + assert((*result.data[4]).into() == 3, 'result[4] = 3'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); assert(*result.shape.at(0) == 2, 'shape[0] = 2'); assert(*result.shape.at(1) == 3, 'shape[1] = 3'); @@ -411,12 +412,12 @@ fn tensor_transpose_2D() { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0).mag == 0, 'result[0] = 0'); - assert(*result.data.at(1).mag == 3, 'result[1] = 3'); - assert(*result.data.at(2).mag == 1, 'result[2] = 1'); - assert(*result.data.at(3).mag == 4, 'result[3] = 4'); - assert(*result.data.at(4).mag == 2, 'result[4] = 2'); - assert(*result.data.at(5).mag == 5, 'result[5] = 5'); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 1, 'result[2] = 1'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + assert((*result.data[4]).into() == 2, 'result[4] = 2'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); assert(*result.shape.at(0) == 3, 'shape[0] = 3'); assert(*result.shape.at(1) == 2, 'shape[1] = 2'); } @@ -433,14 +434,14 @@ fn tensor_transpose_3D() { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0).mag == 0, 'result[0] = 0'); - assert(*result.at(1).mag == 4, 'result[1] = 4'); - assert(*result.at(2).mag == 1, 'result[2] = 1'); - assert(*result.at(3).mag == 5, 'result[3] = 5'); - assert(*result.at(4).mag == 2, 'result[4] = 2'); - assert(*result.at(5).mag == 6, 'result[5] = 6'); - assert(*result.at(6).mag == 3, 'result[6] = 3'); - assert(*result.at(7).mag == 7, 'result[7] = 7'); + assert((*result[0]).into() == 0, 'result[0] = 0'); + assert((*result[1]).into() == 4, 'result[1] = 4'); + assert((*result[2]).into() == 1, 'result[2] = 1'); + assert((*result[3]).into() == 5, 'result[3] = 5'); + assert((*result[4]).into() == 2, 'result[4] = 2'); + assert((*result[5]).into() == 6, 'result[5] = 6'); + assert((*result[6]).into() == 3, 'result[6] = 3'); + assert((*result[7]).into() == 7, 'result[7] = 7'); let mut axes: Array = ArrayTrait::new(); axes.append(2); @@ -449,14 +450,14 @@ fn tensor_transpose_3D() { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0).mag == 0, 'result[0] = 0'); - assert(*result.at(1).mag == 4, 'result[1] = 4'); - assert(*result.at(2).mag == 2, 'result[2] = 2'); - assert(*result.at(3).mag == 6, 'result[3] = 6'); - assert(*result.at(4).mag == 1, 'result[4] = 1'); - assert(*result.at(5).mag == 5, 'result[5] = 5'); - assert(*result.at(6).mag == 3, 'result[6] = 3'); - assert(*result.at(7).mag == 7, 'result[7] = 7'); + assert((*result[0]).into() == 0, 'result[0] = 0'); + assert((*result[1]).into() == 4, 'result[1] = 4'); + assert((*result[2]).into() == 2, 'result[2] = 2'); + assert((*result[3]).into() == 6, 'result[3] = 6'); + assert((*result[4]).into() == 1, 'result[4] = 1'); + assert((*result[5]).into() == 5, 'result[5] = 5'); + assert((*result[6]).into() == 3, 'result[6] = 3'); + assert((*result[7]).into() == 7, 'result[7] = 7'); let mut axes: Array = ArrayTrait::new(); axes.append(0); @@ -465,14 +466,14 @@ fn tensor_transpose_3D() { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0).mag == 0, 'result[0] = 0'); - assert(*result.at(1).mag == 2, 'result[1] = 2'); - assert(*result.at(2).mag == 1, 'result[2] = 1'); - assert(*result.at(3).mag == 3, 'result[3] = 3'); - assert(*result.at(4).mag == 4, 'result[4] = 4'); - assert(*result.at(5).mag == 6, 'result[5] = 6'); - assert(*result.at(6).mag == 5, 'result[6] = 5'); - assert(*result.at(7).mag == 7, 'result[7] = 7'); + assert((*result[0]).into() == 0, 'result[0] = 0'); + assert((*result[1]).into() == 2, 'result[1] = 2'); + assert((*result[2]).into() == 1, 'result[2] = 1'); + assert((*result[3]).into() == 3, 'result[3] = 3'); + assert((*result[4]).into() == 4, 'result[4] = 4'); + assert((*result[5]).into() == 6, 'result[5] = 6'); + assert((*result[6]).into() == 5, 'result[6] = 5'); + assert((*result[7]).into() == 7, 'result[7] = 7'); let tensor = i32_tensor_3x2x2_helper(); @@ -483,18 +484,18 @@ fn tensor_transpose_3D() { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0).mag == 0, 'result[0] = 0'); - assert(*result.data.at(1).mag == 4, 'result[1] = 4'); - assert(*result.data.at(2).mag == 8, 'result[2] = 8'); - assert(*result.data.at(3).mag == 1, 'result[3] = 1'); - assert(*result.data.at(4).mag == 5, 'result[4] = 5'); - assert(*result.data.at(5).mag == 9, 'result[5] = 9'); - assert(*result.data.at(6).mag == 2, 'result[6] = 2'); - assert(*result.data.at(7).mag == 6, 'result[7] = 6'); - assert(*result.data.at(8).mag == 10, 'result[7] = 10'); - assert(*result.data.at(9).mag == 3, 'result[7] = 3'); - assert(*result.data.at(10).mag == 7, 'result[7] = 7'); - assert(*result.data.at(11).mag == 11, 'result[7] = 11'); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 1, 'result[3] = 1'); + assert((*result.data[4]).into() == 5, 'result[4] = 5'); + assert((*result.data[5]).into() == 9, 'result[5] = 9'); + assert((*result.data[6]).into() == 2, 'result[6] = 2'); + assert((*result.data[7]).into() == 6, 'result[7] = 6'); + assert((*result.data[8]).into() == 10, 'result[7] = 10'); + assert((*result.data[9]).into() == 3, 'result[7] = 3'); + assert((*result.data[10]).into() == 7, 'result[7] = 7'); + assert((*result.data[11]).into() == 11, 'result[7] = 11'); assert(*result.shape.at(0) == 2, 'shape[0] = 2'); assert(*result.shape.at(1) == 2, 'shape[1] = 2'); assert(*result.shape.at(2) == 3, 'shape[2] = 3'); @@ -506,18 +507,18 @@ fn tensor_transpose_3D() { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0).mag == 0, 'result[0] = 0'); - assert(*result.data.at(1).mag == 4, 'result[1] = 4'); - assert(*result.data.at(2).mag == 8, 'result[2] = 8'); - assert(*result.data.at(3).mag == 2, 'result[3] = 2'); - assert(*result.data.at(4).mag == 6, 'result[4] = 6'); - assert(*result.data.at(5).mag == 10, 'result[5] = 10'); - assert(*result.data.at(6).mag == 1, 'result[6] = 1'); - assert(*result.data.at(7).mag == 5, 'result[7] = 5'); - assert(*result.data.at(8).mag == 9, 'result[7] = 9'); - assert(*result.data.at(9).mag == 3, 'result[7] = 3'); - assert(*result.data.at(10).mag == 7, 'result[7] = 7'); - assert(*result.data.at(11).mag == 11, 'result[7] = 11'); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 2, 'result[3] = 2'); + assert((*result.data[4]).into() == 6, 'result[4] = 6'); + assert((*result.data[5]).into() == 10, 'result[5] = 10'); + assert((*result.data[6]).into() == 1, 'result[6] = 1'); + assert((*result.data[7]).into() == 5, 'result[7] = 5'); + assert((*result.data[8]).into() == 9, 'result[7] = 9'); + assert((*result.data[9]).into() == 3, 'result[7] = 3'); + assert((*result.data[10]).into() == 7, 'result[7] = 7'); + assert((*result.data[11]).into() == 11, 'result[7] = 11'); assert(*result.shape.at(0) == 2, 'shape[0] = 2'); assert(*result.shape.at(1) == 2, 'shape[1] = 2'); assert(*result.shape.at(2) == 3, 'shape[2] = 3'); @@ -529,18 +530,18 @@ fn tensor_transpose_3D() { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0).mag == 0, 'result[0] = 0'); - assert(*result.data.at(1).mag == 2, 'result[1] = 2'); - assert(*result.data.at(2).mag == 1, 'result[2] = 1'); - assert(*result.data.at(3).mag == 3, 'result[3] = 3'); - assert(*result.data.at(4).mag == 4, 'result[4] = 4'); - assert(*result.data.at(5).mag == 6, 'result[5] = 6'); - assert(*result.data.at(6).mag == 5, 'result[6] = 5'); - assert(*result.data.at(7).mag == 7, 'result[7] = 7'); - assert(*result.data.at(8).mag == 8, 'result[7] = 8'); - assert(*result.data.at(9).mag == 10, 'result[7] = 10'); - assert(*result.data.at(10).mag == 9, 'result[7] = 9'); - assert(*result.data.at(11).mag == 11, 'result[7] = 11'); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 2, 'result[1] = 2'); + assert((*result.data[2]).into() == 1, 'result[2] = 1'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 6, 'result[5] = 6'); + assert((*result.data[6]).into() == 5, 'result[6] = 5'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + assert((*result.data[8]).into() == 8, 'result[7] = 8'); + assert((*result.data[9]).into() == 10, 'result[7] = 10'); + assert((*result.data[10]).into() == 9, 'result[7] = 9'); + assert((*result.data[11]).into() == 11, 'result[7] = 11'); assert(*result.shape.at(0) == 3, 'shape[0] = 3'); assert(*result.shape.at(1) == 2, 'shape[1] = 2'); assert(*result.shape.at(2) == 2, 'shape[2] = 2'); diff --git a/src/tests/performance/quantization_test.cairo b/src/tests/performance/quantization_test.cairo index be8830ab3..cfab4278c 100644 --- a/src/tests/performance/quantization_test.cairo +++ b/src/tests/performance/quantization_test.cairo @@ -1,5 +1,6 @@ use array::ArrayTrait; use array::SpanTrait; +use traits::Into; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; @@ -31,23 +32,12 @@ fn quantize_linear_test() { let mut res = PerfomanceTrait::quantize_linear(@tensor); - assert(*res.data.at(0_usize).mag == 127_u32, '*result[0] == -127'); - assert(*res.data.at(0_usize).sign == true, '*result[0] -> negative'); - - assert(*res.data.at(1_usize).mag == 101_u32, '*result[1] == 101'); - assert(*res.data.at(1_usize).sign == false, '*result[1] -> positive'); - - assert(*res.data.at(2_usize).mag == 51_u32, '*result[2] == -51'); - assert(*res.data.at(2_usize).sign == true, '*result[2] -> negative'); - - assert(*res.data.at(3_usize).mag == 124_u32, '*result[3] == 124'); - assert(*res.data.at(3_usize).sign == false, '*result[3] -> positive'); - - assert(*res.data.at(4_usize).mag == 80_u32, '*result[4] == -80'); - assert(*res.data.at(4_usize).sign == true, '*result[4] -> negative'); - - assert(*res.data.at(5_usize).mag == 64_u32, '*result[5] == 64'); - assert(*res.data.at(5_usize).sign == false, '*result[5] -> positive'); + assert((*res.data[0]).into() == -127, '*result[0] == -127'); + assert((*res.data[1]).into() == 101, '*result[1] == 101'); + assert((*res.data[2]).into() == -51, '*result[2] == -51'); + assert((*res.data[3]).into() == 124, '*result[3] == 124'); + assert((*res.data[4]).into() == -80, '*result[4] == -80'); + assert((*res.data[5]).into() == 64, '*result[5] == 64'); } #[test] @@ -71,21 +61,10 @@ fn quantize_linear_from_fp_test() { let mut res = PerfomanceTrait::::quantize_linear_from_fp(@tensor); - assert(*res.data.at(0_usize).mag == 63, '*result[0] == 63'); - assert(*res.data.at(0_usize).sign == false, '*result[0] -> positive'); - - assert(*res.data.at(1_usize).mag == 95, '*result[1] == 95'); - assert(*res.data.at(1_usize).sign == false, '*result[1] -> positive'); - - assert(*res.data.at(2_usize).mag == 127, '*result[2] == 127'); - assert(*res.data.at(2_usize).sign == false, '*result[2] -> positive'); - - assert(*res.data.at(3_usize).mag == 63, '*result[3] == -63'); - assert(*res.data.at(3_usize).sign == true, '*result[3] -> negative'); - - assert(*res.data.at(4_usize).mag == 95, '*result[4] == -95'); - assert(*res.data.at(4_usize).sign == true, '*result[4] -> negative'); - - assert(*res.data.at(5_usize).mag == 127, '*result[5] == -127'); - assert(*res.data.at(5_usize).sign == true, '*result[5] -> negative'); + assert((*res.data[0]).into() == 63, '*result[0] == 63'); + assert((*res.data[1]).into() == 95, '*result[1] == 95'); + assert((*res.data[2]).into() == 127, '*result[2] == 127'); + assert((*res.data[3]).into() == -63, '*result[3] == -63'); + assert((*res.data[4]).into() == -95, '*result[4] == -95'); + assert((*res.data[5]).into() == -127, '*result[5] == -127'); } From 947b72cb6f3305b572b6956d2487ef20ce022df9 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Sun, 18 Jun 2023 19:07:56 +0300 Subject: [PATCH 005/126] move test helpers directory --- src/tests.cairo | 1 + src/tests/helpers.cairo | 1 + src/tests/helpers/tensor.cairo | 3 +++ src/tests/helpers/tensor/fixed_point.cairo | 2 ++ .../tensor/fixed_point/fp16x16.cairo} | 0 .../tensor/fixed_point/fp8x23.cairo} | 0 .../helpers/helpers_i32.cairo => helpers/tensor/i32.cairo} | 0 .../helpers/helpers_u32.cairo => helpers/tensor/u32.cairo} | 0 src/tests/operators/linalg/matmul_test.cairo | 2 +- .../math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo | 4 ++-- .../math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo | 4 ++-- src/tests/operators/math/argmax/argmax_i32_test.cairo | 4 ++-- src/tests/operators/math/argmax/argmax_u32_test.cairo | 4 ++-- .../math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo | 4 ++-- .../math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo | 4 ++-- src/tests/operators/math/argmin/argmin_i32_test.cairo | 4 ++-- src/tests/operators/math/argmin/argmin_u32_test.cairo | 4 ++-- src/tests/operators/math/exp_test.cairo | 2 +- src/tests/operators/math/ln_test.cairo | 2 +- src/tests/operators/math/max_test.cairo | 2 +- src/tests/operators/math/min_test.cairo | 2 +- src/tests/operators/math/reduce_sum_test.cairo | 4 +--- .../operators/nn/functional/logsoftmax/logsoftmax_test.cairo | 2 +- src/tests/operators/nn/functional/softmax/softmax_test.cairo | 2 +- src/tests/operators/tensor.cairo | 3 +-- src/tests/operators/tensor/helpers.cairo | 3 --- src/tests/operators/tensor/helpers/helpers_fp.cairo | 2 -- src/tests/operators/tensor/tensor_test.cairo | 2 +- 28 files changed, 33 insertions(+), 34 deletions(-) create mode 100644 src/tests/helpers.cairo create mode 100644 src/tests/helpers/tensor.cairo create mode 100644 src/tests/helpers/tensor/fixed_point.cairo rename src/tests/{operators/tensor/helpers/helpers_fp/fp16x16_helpers.cairo => helpers/tensor/fixed_point/fp16x16.cairo} (100%) rename src/tests/{operators/tensor/helpers/helpers_fp/fp8x23_helpers.cairo => helpers/tensor/fixed_point/fp8x23.cairo} (100%) rename src/tests/{operators/tensor/helpers/helpers_i32.cairo => helpers/tensor/i32.cairo} (100%) rename src/tests/{operators/tensor/helpers/helpers_u32.cairo => helpers/tensor/u32.cairo} (100%) delete mode 100644 src/tests/operators/tensor/helpers.cairo delete mode 100644 src/tests/operators/tensor/helpers/helpers_fp.cairo diff --git a/src/tests.cairo b/src/tests.cairo index 6078e871f..c142d6926 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -1,3 +1,4 @@ mod numbers; mod performance; mod operators; +mod helpers; \ No newline at end of file diff --git a/src/tests/helpers.cairo b/src/tests/helpers.cairo new file mode 100644 index 000000000..3344878ea --- /dev/null +++ b/src/tests/helpers.cairo @@ -0,0 +1 @@ +mod tensor; \ No newline at end of file diff --git a/src/tests/helpers/tensor.cairo b/src/tests/helpers/tensor.cairo new file mode 100644 index 000000000..4509b1c62 --- /dev/null +++ b/src/tests/helpers/tensor.cairo @@ -0,0 +1,3 @@ +mod fixed_point; +mod i32; +mod u32; \ No newline at end of file diff --git a/src/tests/helpers/tensor/fixed_point.cairo b/src/tests/helpers/tensor/fixed_point.cairo new file mode 100644 index 000000000..468e9a6a7 --- /dev/null +++ b/src/tests/helpers/tensor/fixed_point.cairo @@ -0,0 +1,2 @@ +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/tests/operators/tensor/helpers/helpers_fp/fp16x16_helpers.cairo b/src/tests/helpers/tensor/fixed_point/fp16x16.cairo similarity index 100% rename from src/tests/operators/tensor/helpers/helpers_fp/fp16x16_helpers.cairo rename to src/tests/helpers/tensor/fixed_point/fp16x16.cairo diff --git a/src/tests/operators/tensor/helpers/helpers_fp/fp8x23_helpers.cairo b/src/tests/helpers/tensor/fixed_point/fp8x23.cairo similarity index 100% rename from src/tests/operators/tensor/helpers/helpers_fp/fp8x23_helpers.cairo rename to src/tests/helpers/tensor/fixed_point/fp8x23.cairo diff --git a/src/tests/operators/tensor/helpers/helpers_i32.cairo b/src/tests/helpers/tensor/i32.cairo similarity index 100% rename from src/tests/operators/tensor/helpers/helpers_i32.cairo rename to src/tests/helpers/tensor/i32.cairo diff --git a/src/tests/operators/tensor/helpers/helpers_u32.cairo b/src/tests/helpers/tensor/u32.cairo similarity index 100% rename from src/tests/operators/tensor/helpers/helpers_u32.cairo rename to src/tests/helpers/tensor/u32.cairo diff --git a/src/tests/operators/linalg/matmul_test.cairo b/src/tests/operators/linalg/matmul_test.cairo index 65a52011f..17ee35cec 100644 --- a/src/tests/operators/linalg/matmul_test.cairo +++ b/src/tests/operators/linalg/matmul_test.cairo @@ -4,7 +4,7 @@ use traits::Into; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::TensorTrait; -use orion::tests::operators::tensor::helpers::helpers_i32::{ +use orion::tests::helpers::tensor::i32::{ i32_tensor_1x3_helper, i32_tensor_2x2_helper, i32_tensor_3x3_helper }; diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo index 2d9a7fc26..df656a21c 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo @@ -119,7 +119,7 @@ mod tensor2x2_argmax_fp { use orion::numbers::fixed_point::implementations::impl_16x16; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_fp::fp16x16_helpers::{ + use orion::tests::helpers::tensor::fixed_point::fp16x16::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; @@ -210,7 +210,7 @@ mod tensor2x2x2_argmax_fp { use orion::numbers::fixed_point::implementations::impl_16x16; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_fp::fp16x16_helpers::{ + use orion::tests::helpers::tensor::fixed_point::fp16x16::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo index 775da8afb..6186a02c3 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo @@ -119,7 +119,7 @@ mod tensor2x2_argmax_fp { use orion::numbers::fixed_point::implementations::impl_8x23; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_fp::fp8x23_helpers::{ + use orion::tests::helpers::tensor::fixed_point::fp8x23::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; @@ -210,7 +210,7 @@ mod tensor2x2x2_argmax_fp { use orion::numbers::fixed_point::implementations::impl_8x23; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_fp::fp8x23_helpers::{ + use orion::tests::helpers::tensor::fixed_point::fp8x23::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; diff --git a/src/tests/operators/math/argmax/argmax_i32_test.cairo b/src/tests/operators/math/argmax/argmax_i32_test.cairo index 4161bcb6a..5d082308e 100644 --- a/src/tests/operators/math/argmax/argmax_i32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_i32_test.cairo @@ -116,7 +116,7 @@ mod tensor2x2_argmax_i32 { use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; + use orion::tests::helpers::tensor::i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; #[test] #[available_gas(20000000)] @@ -203,7 +203,7 @@ mod tensor2x2x2_argmax_i32 { use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; + use orion::tests::helpers::tensor::i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; #[test] #[available_gas(20000000)] diff --git a/src/tests/operators/math/argmax/argmax_u32_test.cairo b/src/tests/operators/math/argmax/argmax_u32_test.cairo index 83821921c..60761ebbe 100644 --- a/src/tests/operators/math/argmax/argmax_u32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_u32_test.cairo @@ -101,7 +101,7 @@ mod tensor2x2_argmax_u32 { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; + use orion::tests::helpers::tensor::u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; #[test] #[available_gas(20000000)] @@ -187,7 +187,7 @@ mod tensor2x2x2_argmax_u32 { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; + use orion::tests::helpers::tensor::u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; #[test] #[available_gas(20000000)] diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo index 49eb88e2f..32f66f0eb 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo @@ -127,7 +127,7 @@ mod tensor2x2_argmin_fp { use orion::numbers::fixed_point::implementations::impl_16x16; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_fp::fp16x16_helpers::{ + use orion::tests::helpers::tensor::fixed_point::fp16x16::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; @@ -229,7 +229,7 @@ mod tensor2x2x2_argmin_fp { use orion::numbers::fixed_point::implementations::impl_16x16; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_fp::fp16x16_helpers::{ + use orion::tests::helpers::tensor::fixed_point::fp16x16::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo index fb15806d6..fbde77b97 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo @@ -127,7 +127,7 @@ mod tensor2x2_argmin_fp { use orion::numbers::fixed_point::implementations::impl_8x23; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_fp::fp8x23_helpers::{ + use orion::tests::helpers::tensor::fixed_point::fp8x23::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; @@ -229,7 +229,7 @@ mod tensor2x2x2_argmin_fp { use orion::numbers::fixed_point::implementations::impl_8x23; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_fp::fp8x23_helpers::{ + use orion::tests::helpers::tensor::fixed_point::fp8x23::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; diff --git a/src/tests/operators/math/argmin/argmin_i32_test.cairo b/src/tests/operators/math/argmin/argmin_i32_test.cairo index e678c2321..16edbf02f 100644 --- a/src/tests/operators/math/argmin/argmin_i32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_i32_test.cairo @@ -125,7 +125,7 @@ mod tensor2x2_argmin_i32 { use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; + use orion::tests::helpers::tensor::i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; #[test] #[available_gas(20000000)] @@ -224,7 +224,7 @@ mod tensor2x2x2_argmin_i32 { use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; + use orion::tests::helpers::tensor::i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; #[test] #[available_gas(20000000)] diff --git a/src/tests/operators/math/argmin/argmin_u32_test.cairo b/src/tests/operators/math/argmin/argmin_u32_test.cairo index 5e3341ff4..9ae02f42d 100644 --- a/src/tests/operators/math/argmin/argmin_u32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_u32_test.cairo @@ -110,7 +110,7 @@ mod tensor2x2_argmin_u32 { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; + use orion::tests::helpers::tensor::u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; #[test] #[available_gas(20000000)] @@ -208,7 +208,7 @@ mod tensor2x2x2_argmin_u32 { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - use orion::tests::operators::tensor::helpers::helpers_u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; + use orion::tests::helpers::tensor::u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; #[test] #[available_gas(20000000)] diff --git a/src/tests/operators/math/exp_test.cairo b/src/tests/operators/math/exp_test.cairo index b058631dd..46925ec2a 100644 --- a/src/tests/operators/math/exp_test.cairo +++ b/src/tests/operators/math/exp_test.cairo @@ -3,7 +3,7 @@ use traits::Into; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::{TensorTrait, }; -use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::numbers::fixed_point::implementations::impl_16x16; #[test] diff --git a/src/tests/operators/math/ln_test.cairo b/src/tests/operators/math/ln_test.cairo index a433c6909..9dea5619e 100644 --- a/src/tests/operators/math/ln_test.cairo +++ b/src/tests/operators/math/ln_test.cairo @@ -4,7 +4,7 @@ use array::ArrayTrait; use orion::operators::tensor::implementations::impl_tensor_i32; -use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::numbers::fixed_point::implementations::impl_16x16; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; diff --git a/src/tests/operators/math/max_test.cairo b/src/tests/operators/math/max_test.cairo index f25b085ed..592d1ff0b 100644 --- a/src/tests/operators/math/max_test.cairo +++ b/src/tests/operators/math/max_test.cairo @@ -1,6 +1,6 @@ use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::TensorTrait; -use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/math/min_test.cairo b/src/tests/operators/math/min_test.cairo index 6790676e2..e321f9857 100644 --- a/src/tests/operators/math/min_test.cairo +++ b/src/tests/operators/math/min_test.cairo @@ -1,6 +1,6 @@ use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::TensorTrait; -use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/math/reduce_sum_test.cairo b/src/tests/operators/math/reduce_sum_test.cairo index c163fed7b..b8dc23ebc 100644 --- a/src/tests/operators/math/reduce_sum_test.cairo +++ b/src/tests/operators/math/reduce_sum_test.cairo @@ -3,9 +3,7 @@ use traits::Into; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::TensorTrait; -use orion::tests::operators::tensor::helpers::helpers_i32::{ - i32_tensor_2x2x2_helper, i32_tensor_1x3_helper -}; +use orion::tests::helpers::tensor::i32::{i32_tensor_2x2x2_helper, i32_tensor_1x3_helper}; use debug::PrintTrait; diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo index 7510c7278..a62dc7ed5 100644 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo @@ -1,7 +1,7 @@ use array::SpanTrait; use traits::Into; -use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; diff --git a/src/tests/operators/nn/functional/softmax/softmax_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_test.cairo index 3716cee06..910745aab 100644 --- a/src/tests/operators/nn/functional/softmax/softmax_test.cairo +++ b/src/tests/operators/nn/functional/softmax/softmax_test.cairo @@ -1,7 +1,7 @@ use array::SpanTrait; use traits::Into; -use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; diff --git a/src/tests/operators/tensor.cairo b/src/tests/operators/tensor.cairo index 86a6bba77..0143edfc3 100644 --- a/src/tests/operators/tensor.cairo +++ b/src/tests/operators/tensor.cairo @@ -1,2 +1 @@ -mod tensor_test; -mod helpers; +mod tensor_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/helpers.cairo b/src/tests/operators/tensor/helpers.cairo deleted file mode 100644 index 8284650f9..000000000 --- a/src/tests/operators/tensor/helpers.cairo +++ /dev/null @@ -1,3 +0,0 @@ -mod helpers_u32; -mod helpers_i32; -mod helpers_fp; \ No newline at end of file diff --git a/src/tests/operators/tensor/helpers/helpers_fp.cairo b/src/tests/operators/tensor/helpers/helpers_fp.cairo deleted file mode 100644 index f80e66701..000000000 --- a/src/tests/operators/tensor/helpers/helpers_fp.cairo +++ /dev/null @@ -1,2 +0,0 @@ -mod fp8x23_helpers; -mod fp16x16_helpers; \ No newline at end of file diff --git a/src/tests/operators/tensor/tensor_test.cairo b/src/tests/operators/tensor/tensor_test.cairo index 3e4390b4e..d1787cf33 100644 --- a/src/tests/operators/tensor/tensor_test.cairo +++ b/src/tests/operators/tensor/tensor_test.cairo @@ -5,7 +5,7 @@ use traits::Into; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::{TensorTrait, ExtraParams, ravel_index, unravel_index}; -use orion::tests::operators::tensor::helpers::helpers_i32::{ +use orion::tests::helpers::tensor::i32::{ i32_tensor_2x2_helper, i32_tensor_3x2_helper, i32_tensor_2x3_helper, i32_tensor_2x2x2_helper, i32_tensor_3x2x2_helper }; From c4c6e10752f53fbc80206f7f5eff2bebb42ca0f3 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Sun, 18 Jun 2023 19:52:12 +0300 Subject: [PATCH 006/126] add negative tensor helpers --- .../helpers/tensor/fixed_point/fp16x16.cairo | 161 +++++++++++++++++ .../helpers/tensor/fixed_point/fp8x23.cairo | 163 ++++++++++++++++++ src/tests/helpers/tensor/i32.cairo | 161 +++++++++++++++++ .../operators/math/abs/abs_fp_test.cairo | 1 - .../operators/math/abs/abs_u32_test.cairo | 2 - .../argmax_fp_test/argmax_fp16x16_test.cairo | 9 +- .../argmax_fp_test/argmax_fp8x23_test.cairo | 9 +- .../math/argmax/argmax_i32_test.cairo | 9 +- .../math/argmax/argmax_u32_test.cairo | 9 +- .../argmin_fp_test/argmin_fp16x16_test.cairo | 9 +- .../argmin_fp_test/argmin_fp8x23_test.cairo | 9 +- .../math/argmin/argmin_i32_test.cairo | 9 +- .../math/argmin/argmin_u32_test.cairo | 9 +- 13 files changed, 509 insertions(+), 51 deletions(-) diff --git a/src/tests/helpers/tensor/fixed_point/fp16x16.cairo b/src/tests/helpers/tensor/fixed_point/fp16x16.cairo index b473de728..446a3b59b 100644 --- a/src/tests/helpers/tensor/fixed_point/fp16x16.cairo +++ b/src/tests/helpers/tensor/fixed_point/fp16x16.cairo @@ -21,6 +21,21 @@ fn fp_tensor_1x3_helper() -> Tensor { return tensor; } +fn fp_tensor_1x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + // 2D fn fp_tensor_2x2_helper() -> Tensor { @@ -40,6 +55,23 @@ fn fp_tensor_2x2_helper() -> Tensor { return tensor; } +fn fp_tensor_2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_3x3_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -63,6 +95,29 @@ fn fp_tensor_3x3_helper() -> Tensor { return tensor; } +fn fp_tensor_3x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new(6, true)); + data.append(FixedTrait::new(7, true)); + data.append(FixedTrait::new(8, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_3x2_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -83,6 +138,26 @@ fn fp_tensor_3x2_helper() -> Tensor { return tensor; } +fn fp_tensor_3x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_3x1_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -100,6 +175,23 @@ fn fp_tensor_3x1_helper() -> Tensor { return tensor; } +fn fp_tensor_3x1_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(1); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_2x3_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -120,6 +212,26 @@ fn fp_tensor_2x3_helper() -> Tensor { return tensor; } +fn fp_tensor_2x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + // 3D fn fp_tensor_2x2x2_helper() -> Tensor { @@ -145,6 +257,29 @@ fn fp_tensor_2x2x2_helper() -> Tensor { return tensor; } +fn fp_tensor_2x2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new(6, true)); + data.append(FixedTrait::new(7, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_3x2x2_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -172,3 +307,29 @@ fn fp_tensor_3x2x2_helper() -> Tensor { return tensor; } +fn fp_tensor_3x2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new(6, true)); + data.append(FixedTrait::new(7, true)); + data.append(FixedTrait::new(8, true)); + data.append(FixedTrait::new(9, true)); + data.append(FixedTrait::new(10, true)); + data.append(FixedTrait::new(11, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} \ No newline at end of file diff --git a/src/tests/helpers/tensor/fixed_point/fp8x23.cairo b/src/tests/helpers/tensor/fixed_point/fp8x23.cairo index 03108ce41..f2c27a8de 100644 --- a/src/tests/helpers/tensor/fixed_point/fp8x23.cairo +++ b/src/tests/helpers/tensor/fixed_point/fp8x23.cairo @@ -21,6 +21,21 @@ fn fp_tensor_1x3_helper() -> Tensor { return tensor; } +fn fp_tensor_1x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + // 2D fn fp_tensor_2x2_helper() -> Tensor { @@ -40,6 +55,23 @@ fn fp_tensor_2x2_helper() -> Tensor { return tensor; } +fn fp_tensor_2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_3x3_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -63,6 +95,29 @@ fn fp_tensor_3x3_helper() -> Tensor { return tensor; } +fn fp_tensor_3x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new(6, true)); + data.append(FixedTrait::new(7, true)); + data.append(FixedTrait::new(8, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_3x2_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -83,6 +138,26 @@ fn fp_tensor_3x2_helper() -> Tensor { return tensor; } +fn fp_tensor_3x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_3x1_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -100,6 +175,23 @@ fn fp_tensor_3x1_helper() -> Tensor { return tensor; } +fn fp_tensor_3x1_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(1); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_2x3_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -120,6 +212,26 @@ fn fp_tensor_2x3_helper() -> Tensor { return tensor; } +fn fp_tensor_2x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + // 3D fn fp_tensor_2x2x2_helper() -> Tensor { @@ -145,6 +257,29 @@ fn fp_tensor_2x2x2_helper() -> Tensor { return tensor; } +fn fp_tensor_2x2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new(6, true)); + data.append(FixedTrait::new(7, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn fp_tensor_3x2x2_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -172,3 +307,31 @@ fn fp_tensor_3x2x2_helper() -> Tensor { return tensor; } +fn fp_tensor_3x2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new(0, false)); + data.append(FixedTrait::new(1, true)); + data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new(4, true)); + data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new(6, true)); + data.append(FixedTrait::new(7, true)); + data.append(FixedTrait::new(8, true)); + data.append(FixedTrait::new(9, true)); + data.append(FixedTrait::new(10, true)); + data.append(FixedTrait::new(11, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + + diff --git a/src/tests/helpers/tensor/i32.cairo b/src/tests/helpers/tensor/i32.cairo index 9c3fb3d76..d9bd95da3 100644 --- a/src/tests/helpers/tensor/i32.cairo +++ b/src/tests/helpers/tensor/i32.cairo @@ -22,6 +22,21 @@ fn i32_tensor_1x3_helper() -> Tensor { return tensor; } +fn i32_tensor_1x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0_u32, false)); + data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(2_u32, true)); + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + // 2D fn i32_tensor_2x2_helper() -> Tensor { @@ -41,6 +56,23 @@ fn i32_tensor_2x2_helper() -> Tensor { return tensor; } +fn i32_tensor_2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0_u32, false)); + data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(3_u32, true)); + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn i32_tensor_3x3_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -64,6 +96,29 @@ fn i32_tensor_3x3_helper() -> Tensor { return tensor; } +fn i32_tensor_3x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0_u32, false)); + data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(3_u32, true)); + data.append(IntegerTrait::new(4_u32, true)); + data.append(IntegerTrait::new(5_u32, true)); + data.append(IntegerTrait::new(6_u32, true)); + data.append(IntegerTrait::new(7_u32, true)); + data.append(IntegerTrait::new(8_u32, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn i32_tensor_3x2_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -84,6 +139,26 @@ fn i32_tensor_3x2_helper() -> Tensor { return tensor; } +fn i32_tensor_3x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0_u32, false)); + data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(3_u32, true)); + data.append(IntegerTrait::new(4_u32, true)); + data.append(IntegerTrait::new(5_u32, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn i32_tensor_3x1_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -101,6 +176,23 @@ fn i32_tensor_3x1_helper() -> Tensor { return tensor; } +fn i32_tensor_3x1_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(1); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0_u32, false)); + data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(2_u32, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn i32_tensor_2x3_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -121,6 +213,26 @@ fn i32_tensor_2x3_helper() -> Tensor { return tensor; } +fn i32_tensor_2x3_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(3); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0_u32, false)); + data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(3_u32, true)); + data.append(IntegerTrait::new(4_u32, true)); + data.append(IntegerTrait::new(5_u32, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + // 3D fn i32_tensor_2x2x2_helper() -> Tensor { @@ -146,6 +258,29 @@ fn i32_tensor_2x2x2_helper() -> Tensor { return tensor; } +fn i32_tensor_2x2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0_u32, false)); + data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(3_u32, true)); + data.append(IntegerTrait::new(4_u32, true)); + data.append(IntegerTrait::new(5_u32, true)); + data.append(IntegerTrait::new(6_u32, true)); + data.append(IntegerTrait::new(7_u32, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} + fn i32_tensor_3x2x2_helper() -> Tensor { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -173,3 +308,29 @@ fn i32_tensor_3x2x2_helper() -> Tensor { return tensor; } +fn i32_tensor_3x2x2_neg_helper() -> Tensor { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0_u32, false)); + data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(3_u32, true)); + data.append(IntegerTrait::new(4_u32, true)); + data.append(IntegerTrait::new(5_u32, true)); + data.append(IntegerTrait::new(6_u32, true)); + data.append(IntegerTrait::new(7_u32, true)); + data.append(IntegerTrait::new(8_u32, true)); + data.append(IntegerTrait::new(9_u32, true)); + data.append(IntegerTrait::new(10_u32, true)); + data.append(IntegerTrait::new(11_u32, true)); + + let extra = Option::::None(()); + + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + return tensor; +} diff --git a/src/tests/operators/math/abs/abs_fp_test.cairo b/src/tests/operators/math/abs/abs_fp_test.cairo index 8f5b7804d..8ae1251bb 100644 --- a/src/tests/operators/math/abs/abs_fp_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test.cairo @@ -7,7 +7,6 @@ use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23; - #[test] #[available_gas(2000000)] fn tensor_abs_fp() { diff --git a/src/tests/operators/math/abs/abs_u32_test.cairo b/src/tests/operators/math/abs/abs_u32_test.cairo index cbfa65ccd..c314f9fe9 100644 --- a/src/tests/operators/math/abs/abs_u32_test.cairo +++ b/src/tests/operators/math/abs/abs_u32_test.cairo @@ -3,8 +3,6 @@ use array::ArrayTrait; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - - #[test] #[available_gas(2000000)] fn tensor_abs_u32() { diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo index df656a21c..918c81c19 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D_argmax_fp { +mod tensor1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; @@ -110,10 +110,8 @@ mod tensor1D_argmax_fp { } } - - #[cfg(test)] -mod tensor2x2_argmax_fp { +mod tensor2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; @@ -202,9 +200,8 @@ mod tensor2x2_argmax_fp { } } - #[cfg(test)] -mod tensor2x2x2_argmax_fp { +mod tensor3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo index 6186a02c3..15026a3be 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D_argmax_fp { +mod tensor1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; @@ -110,10 +110,8 @@ mod tensor1D_argmax_fp { } } - - #[cfg(test)] -mod tensor2x2_argmax_fp { +mod tensor2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; @@ -202,9 +200,8 @@ mod tensor2x2_argmax_fp { } } - #[cfg(test)] -mod tensor2x2x2_argmax_fp { +mod tensor3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; diff --git a/src/tests/operators/math/argmax/argmax_i32_test.cairo b/src/tests/operators/math/argmax/argmax_i32_test.cairo index 5d082308e..28ba322cb 100644 --- a/src/tests/operators/math/argmax/argmax_i32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_i32_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D_argmax_i32 { +mod tensor1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -108,10 +108,8 @@ mod tensor1D_argmax_i32 { } } - - #[cfg(test)] -mod tensor2x2_argmax_i32 { +mod tensor2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -196,9 +194,8 @@ mod tensor2x2_argmax_i32 { } } - #[cfg(test)] -mod tensor2x2x2_argmax_i32 { +mod tensor3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; diff --git a/src/tests/operators/math/argmax/argmax_u32_test.cairo b/src/tests/operators/math/argmax/argmax_u32_test.cairo index 60761ebbe..7728a140a 100644 --- a/src/tests/operators/math/argmax/argmax_u32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_u32_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D_argmax_u32 { +mod tensor1D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -94,10 +94,8 @@ mod tensor1D_argmax_u32 { } } - - #[cfg(test)] -mod tensor2x2_argmax_u32 { +mod tensor2D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -181,9 +179,8 @@ mod tensor2x2_argmax_u32 { } } - #[cfg(test)] -mod tensor2x2x2_argmax_u32 { +mod tensor3D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo index 32f66f0eb..6abd8b3af 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D_argmin_fp { +mod tensor1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; @@ -118,10 +118,8 @@ mod tensor1D_argmin_fp { } } - - #[cfg(test)] -mod tensor2x2_argmin_fp { +mod tensor2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; @@ -221,9 +219,8 @@ mod tensor2x2_argmin_fp { } } - #[cfg(test)] -mod tensor2x2x2_argmin_fp { +mod tensor3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo index fbde77b97..2677a83fb 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D_argmin_fp { +mod tensor1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; @@ -118,10 +118,8 @@ mod tensor1D_argmin_fp { } } - - #[cfg(test)] -mod tensor2x2_argmin_fp { +mod tensor2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; @@ -221,9 +219,8 @@ mod tensor2x2_argmin_fp { } } - #[cfg(test)] -mod tensor2x2x2_argmin_fp { +mod tensor3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; diff --git a/src/tests/operators/math/argmin/argmin_i32_test.cairo b/src/tests/operators/math/argmin/argmin_i32_test.cairo index 16edbf02f..003d85555 100644 --- a/src/tests/operators/math/argmin/argmin_i32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_i32_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D_argmin_i32 { +mod tensor1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -117,10 +117,8 @@ mod tensor1D_argmin_i32 { } } - - #[cfg(test)] -mod tensor2x2_argmin_i32 { +mod tensor2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -217,9 +215,8 @@ mod tensor2x2_argmin_i32 { } } - #[cfg(test)] -mod tensor2x2x2_argmin_i32 { +mod tensor3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; diff --git a/src/tests/operators/math/argmin/argmin_u32_test.cairo b/src/tests/operators/math/argmin/argmin_u32_test.cairo index 9ae02f42d..ff024cf1b 100644 --- a/src/tests/operators/math/argmin/argmin_u32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_u32_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D_argmin_u32 { +mod tensor1D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -103,10 +103,8 @@ mod tensor1D_argmin_u32 { } } - - #[cfg(test)] -mod tensor2x2_argmin_u32 { +mod tensor2D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -202,9 +200,8 @@ mod tensor2x2_argmin_u32 { } } - #[cfg(test)] -mod tensor2x2x2_argmin_u32 { +mod tensor3D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; From ceb6e316e9cbb5358226087430fb608053c1940f Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Mon, 19 Jun 2023 11:44:20 +0300 Subject: [PATCH 007/126] refactor matmul tests --- .../helpers/tensor/fixed_point/fp16x16.cairo | 204 ++++++------- .../helpers/tensor/fixed_point/fp8x23.cairo | 279 +++++++++--------- src/tests/operators/linalg.cairo | 2 +- src/tests/operators/linalg/matmul.cairo | 3 + .../linalg/matmul/matmul_fp_test.cairo | 2 + .../matmul_fp_test/matmul_fp16x16_test.cairo | 71 +++++ .../matmul_fp_test/matmul_fp8x23_test.cairo | 71 +++++ .../matmul_i32_test.cairo} | 12 +- .../linalg/matmul/matmul_u32_test.cairo | 68 +++++ 9 files changed, 467 insertions(+), 245 deletions(-) create mode 100644 src/tests/operators/linalg/matmul.cairo create mode 100644 src/tests/operators/linalg/matmul/matmul_fp_test.cairo create mode 100644 src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo create mode 100644 src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo rename src/tests/operators/linalg/{matmul_test.cairo => matmul/matmul_i32_test.cairo} (93%) create mode 100644 src/tests/operators/linalg/matmul/matmul_u32_test.cairo diff --git a/src/tests/helpers/tensor/fixed_point/fp16x16.cairo b/src/tests/helpers/tensor/fixed_point/fp16x16.cairo index 446a3b59b..279f6df41 100644 --- a/src/tests/helpers/tensor/fixed_point/fp16x16.cairo +++ b/src/tests/helpers/tensor/fixed_point/fp16x16.cairo @@ -11,9 +11,9 @@ fn fp_tensor_1x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -26,9 +26,9 @@ fn fp_tensor_1x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -44,10 +44,10 @@ fn fp_tensor_2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -61,10 +61,10 @@ fn fp_tensor_2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -78,15 +78,15 @@ fn fp_tensor_3x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); - data.append(FixedTrait::new(6, false)); - data.append(FixedTrait::new(7, false)); - data.append(FixedTrait::new(8, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); + data.append(FixedTrait::new_unscaled(6, false)); + data.append(FixedTrait::new_unscaled(7, false)); + data.append(FixedTrait::new_unscaled(8, false)); let extra = Option::::None(()); @@ -101,15 +101,15 @@ fn fp_tensor_3x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); - data.append(FixedTrait::new(6, true)); - data.append(FixedTrait::new(7, true)); - data.append(FixedTrait::new(8, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); + data.append(FixedTrait::new_unscaled(6, true)); + data.append(FixedTrait::new_unscaled(7, true)); + data.append(FixedTrait::new_unscaled(8, true)); let extra = Option::::None(()); @@ -124,12 +124,12 @@ fn fp_tensor_3x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); let extra = Option::::None(()); @@ -144,12 +144,12 @@ fn fp_tensor_3x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); let extra = Option::::None(()); @@ -164,9 +164,9 @@ fn fp_tensor_3x1_helper() -> Tensor { sizes.append(1); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); let extra = Option::::None(()); @@ -181,9 +181,9 @@ fn fp_tensor_3x1_neg_helper() -> Tensor { sizes.append(1); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); let extra = Option::::None(()); @@ -198,12 +198,12 @@ fn fp_tensor_2x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); let extra = Option::::None(()); @@ -218,12 +218,12 @@ fn fp_tensor_2x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); let extra = Option::::None(()); @@ -241,14 +241,14 @@ fn fp_tensor_2x2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); - data.append(FixedTrait::new(6, false)); - data.append(FixedTrait::new(7, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); + data.append(FixedTrait::new_unscaled(6, false)); + data.append(FixedTrait::new_unscaled(7, false)); let extra = Option::::None(()); @@ -264,14 +264,14 @@ fn fp_tensor_2x2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); - data.append(FixedTrait::new(6, true)); - data.append(FixedTrait::new(7, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); + data.append(FixedTrait::new_unscaled(6, true)); + data.append(FixedTrait::new_unscaled(7, true)); let extra = Option::::None(()); @@ -287,18 +287,18 @@ fn fp_tensor_3x2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); - data.append(FixedTrait::new(6, false)); - data.append(FixedTrait::new(7, false)); - data.append(FixedTrait::new(8, false)); - data.append(FixedTrait::new(9, false)); - data.append(FixedTrait::new(10, false)); - data.append(FixedTrait::new(11, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); + data.append(FixedTrait::new_unscaled(6, false)); + data.append(FixedTrait::new_unscaled(7, false)); + data.append(FixedTrait::new_unscaled(8, false)); + data.append(FixedTrait::new_unscaled(9, false)); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(11, false)); let extra = Option::::None(()); @@ -314,18 +314,18 @@ fn fp_tensor_3x2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); - data.append(FixedTrait::new(6, true)); - data.append(FixedTrait::new(7, true)); - data.append(FixedTrait::new(8, true)); - data.append(FixedTrait::new(9, true)); - data.append(FixedTrait::new(10, true)); - data.append(FixedTrait::new(11, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); + data.append(FixedTrait::new_unscaled(6, true)); + data.append(FixedTrait::new_unscaled(7, true)); + data.append(FixedTrait::new_unscaled(8, true)); + data.append(FixedTrait::new_unscaled(9, true)); + data.append(FixedTrait::new_unscaled(10, true)); + data.append(FixedTrait::new_unscaled(11, true)); let extra = Option::::None(()); diff --git a/src/tests/helpers/tensor/fixed_point/fp8x23.cairo b/src/tests/helpers/tensor/fixed_point/fp8x23.cairo index f2c27a8de..2b978cd46 100644 --- a/src/tests/helpers/tensor/fixed_point/fp8x23.cairo +++ b/src/tests/helpers/tensor/fixed_point/fp8x23.cairo @@ -1,6 +1,6 @@ use array::ArrayTrait; use array::SpanTrait; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23; use orion::operators::tensor::implementations::impl_tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -11,12 +11,12 @@ fn fp_tensor_1x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - let extra = Option::::None(()); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -26,12 +26,12 @@ fn fp_tensor_1x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - let extra = Option::::None(()); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -44,13 +44,13 @@ fn fp_tensor_2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - let extra = Option::::None(()); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -61,13 +61,13 @@ fn fp_tensor_2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - let extra = Option::::None(()); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -78,19 +78,19 @@ fn fp_tensor_3x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); - data.append(FixedTrait::new(6, false)); - data.append(FixedTrait::new(7, false)); - data.append(FixedTrait::new(8, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); + data.append(FixedTrait::new_unscaled(6, false)); + data.append(FixedTrait::new_unscaled(7, false)); + data.append(FixedTrait::new_unscaled(8, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -101,19 +101,19 @@ fn fp_tensor_3x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); - data.append(FixedTrait::new(6, true)); - data.append(FixedTrait::new(7, true)); - data.append(FixedTrait::new(8, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); + data.append(FixedTrait::new_unscaled(6, true)); + data.append(FixedTrait::new_unscaled(7, true)); + data.append(FixedTrait::new_unscaled(8, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -124,16 +124,16 @@ fn fp_tensor_3x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -144,16 +144,16 @@ fn fp_tensor_3x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -164,13 +164,13 @@ fn fp_tensor_3x1_helper() -> Tensor { sizes.append(1); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -181,13 +181,13 @@ fn fp_tensor_3x1_neg_helper() -> Tensor { sizes.append(1); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -198,16 +198,16 @@ fn fp_tensor_2x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -218,16 +218,16 @@ fn fp_tensor_2x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -241,18 +241,18 @@ fn fp_tensor_2x2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); - data.append(FixedTrait::new(6, false)); - data.append(FixedTrait::new(7, false)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); + data.append(FixedTrait::new_unscaled(6, false)); + data.append(FixedTrait::new_unscaled(7, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -264,18 +264,18 @@ fn fp_tensor_2x2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); - data.append(FixedTrait::new(6, true)); - data.append(FixedTrait::new(7, true)); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); + data.append(FixedTrait::new_unscaled(6, true)); + data.append(FixedTrait::new_unscaled(7, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -287,22 +287,22 @@ fn fp_tensor_3x2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, false)); - data.append(FixedTrait::new(2, false)); - data.append(FixedTrait::new(3, false)); - data.append(FixedTrait::new(4, false)); - data.append(FixedTrait::new(5, false)); - data.append(FixedTrait::new(6, false)); - data.append(FixedTrait::new(7, false)); - data.append(FixedTrait::new(8, false)); - data.append(FixedTrait::new(9, false)); - data.append(FixedTrait::new(10, false)); - data.append(FixedTrait::new(11, false)); - - let extra = Option::::None(()); - - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(4, false)); + data.append(FixedTrait::new_unscaled(5, false)); + data.append(FixedTrait::new_unscaled(6, false)); + data.append(FixedTrait::new_unscaled(7, false)); + data.append(FixedTrait::new_unscaled(8, false)); + data.append(FixedTrait::new_unscaled(9, false)); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(11, false)); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } @@ -314,24 +314,23 @@ fn fp_tensor_3x2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(FixedTrait::new(0, false)); - data.append(FixedTrait::new(1, true)); - data.append(FixedTrait::new(2, true)); - data.append(FixedTrait::new(3, true)); - data.append(FixedTrait::new(4, true)); - data.append(FixedTrait::new(5, true)); - data.append(FixedTrait::new(6, true)); - data.append(FixedTrait::new(7, true)); - data.append(FixedTrait::new(8, true)); - data.append(FixedTrait::new(9, true)); - data.append(FixedTrait::new(10, true)); - data.append(FixedTrait::new(11, true)); - - let extra = Option::::None(()); - - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, true)); + data.append(FixedTrait::new_unscaled(2, true)); + data.append(FixedTrait::new_unscaled(3, true)); + data.append(FixedTrait::new_unscaled(4, true)); + data.append(FixedTrait::new_unscaled(5, true)); + data.append(FixedTrait::new_unscaled(6, true)); + data.append(FixedTrait::new_unscaled(7, true)); + data.append(FixedTrait::new_unscaled(8, true)); + data.append(FixedTrait::new_unscaled(9, true)); + data.append(FixedTrait::new_unscaled(10, true)); + data.append(FixedTrait::new_unscaled(11, true)); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); return tensor; } - diff --git a/src/tests/operators/linalg.cairo b/src/tests/operators/linalg.cairo index f17c70bfd..2ecbda881 100644 --- a/src/tests/operators/linalg.cairo +++ b/src/tests/operators/linalg.cairo @@ -1 +1 @@ -mod matmul_test; +mod matmul; diff --git a/src/tests/operators/linalg/matmul.cairo b/src/tests/operators/linalg/matmul.cairo new file mode 100644 index 000000000..47bbb1ecb --- /dev/null +++ b/src/tests/operators/linalg/matmul.cairo @@ -0,0 +1,3 @@ +mod matmul_i32_test; +mod matmul_u32_test; +mod matmul_fp_test; \ No newline at end of file diff --git a/src/tests/operators/linalg/matmul/matmul_fp_test.cairo b/src/tests/operators/linalg/matmul/matmul_fp_test.cairo new file mode 100644 index 000000000..daa937c51 --- /dev/null +++ b/src/tests/operators/linalg/matmul/matmul_fp_test.cairo @@ -0,0 +1,2 @@ +mod matmul_fp8x23_test; +mod matmul_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo b/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo new file mode 100644 index 000000000..fa6e7a843 --- /dev/null +++ b/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo @@ -0,0 +1,71 @@ +use array::ArrayTrait; +use array::SpanTrait; +use traits::Into; + +use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::core::FixedTrait; +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::TensorTrait; +use orion::tests::helpers::tensor::fixed_point::fp16x16::{ + fp_tensor_1x3_helper, fp_tensor_2x2_helper, fp_tensor_3x3_helper +}; + +#[test] +#[available_gas(200000000)] +fn matmul_1Dx1D() { + //! Case: Dot product (1D x 1D) + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == FixedTrait::from_unscaled_felt(5), 'result[0] = 5'); + assert(result.data.len() == 1, 'data len is 1'); + assert(result.shape.len() == 1, 'shape len is 1'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_2Dx2D() { + //! Case: Matrix multiplication (2D x 2D) + let tensor_1 = fp_tensor_2x2_helper(); + let tensor_2 = fp_tensor_2x2_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == FixedTrait::from_unscaled_felt(2), 'result[0] = 2'); + assert((*result.data[1]).into() == FixedTrait::from_unscaled_felt(3), 'result[1] = 3'); + assert((*result.data[2]).into() == FixedTrait::from_unscaled_felt(6), 'result[2] = 6'); + assert((*result.data[3]).into() == FixedTrait::from_unscaled_felt(11), 'result[3] = 11'); + assert(result.data.len() == 4, 'data len is 4'); + assert(result.shape.len() == 2, 'shape len is 2'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_2Dx1D() { + //! Case: Matrix-Vector multiplication (2D x 1D) + let tensor_1 = fp_tensor_3x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == FixedTrait::from_unscaled_felt(5), 'result[0] = 5'); + assert((*result.data[1]).into() == FixedTrait::from_unscaled_felt(14), 'result[1] = 14'); + assert((*result.data[2]).into() == FixedTrait::from_unscaled_felt(23), 'result[2] = 23'); + assert(result.data.len() == 3, 'data len is 3'); + assert(result.shape.len() == 1, 'shape len is 1'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_1Dx2D() { + //! Case: Matrix-Vector multiplication (1D x 2D) + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_3x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == FixedTrait::from_unscaled_felt(15), 'result[0] = 15'); + assert((*result.data[1]).into() == FixedTrait::from_unscaled_felt(18), 'result[1] = 18'); + assert((*result.data[2]).into() == FixedTrait::from_unscaled_felt(21), 'result[2] = 21'); + assert(result.data.len() == 3, 'data len is 3'); + assert(result.shape.len() == 1, 'shape len is 1'); +} + diff --git a/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo b/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo new file mode 100644 index 000000000..01e507caf --- /dev/null +++ b/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo @@ -0,0 +1,71 @@ +use array::ArrayTrait; +use array::SpanTrait; +use traits::Into; + +use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::core::FixedTrait; +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::TensorTrait; +use orion::tests::helpers::tensor::fixed_point::fp8x23::{ + fp_tensor_1x3_helper, fp_tensor_2x2_helper, fp_tensor_3x3_helper +}; + +#[test] +#[available_gas(200000000)] +fn matmul_1Dx1D() { + //! Case: Dot product (1D x 1D) + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == FixedTrait::from_unscaled_felt(5), 'result[0] = 5'); + assert(result.data.len() == 1, 'data len is 1'); + assert(result.shape.len() == 1, 'shape len is 1'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_2Dx2D() { + //! Case: Matrix multiplication (2D x 2D) + let tensor_1 = fp_tensor_2x2_helper(); + let tensor_2 = fp_tensor_2x2_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == FixedTrait::from_unscaled_felt(2), 'result[0] = 2'); + assert((*result.data[1]).into() == FixedTrait::from_unscaled_felt(3), 'result[1] = 3'); + assert((*result.data[2]).into() == FixedTrait::from_unscaled_felt(6), 'result[2] = 6'); + assert((*result.data[3]).into() == FixedTrait::from_unscaled_felt(11), 'result[3] = 11'); + assert(result.data.len() == 4, 'data len is 4'); + assert(result.shape.len() == 2, 'shape len is 2'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_2Dx1D() { + //! Case: Matrix-Vector multiplication (2D x 1D) + let tensor_1 = fp_tensor_3x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == FixedTrait::from_unscaled_felt(5), 'result[0] = 5'); + assert((*result.data[1]).into() == FixedTrait::from_unscaled_felt(14), 'result[1] = 14'); + assert((*result.data[2]).into() == FixedTrait::from_unscaled_felt(23), 'result[2] = 23'); + assert(result.data.len() == 3, 'data len is 3'); + assert(result.shape.len() == 1, 'shape len is 1'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_1Dx2D() { + //! Case: Matrix-Vector multiplication (1D x 2D) + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_3x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == FixedTrait::from_unscaled_felt(15), 'result[0] = 15'); + assert((*result.data[1]).into() == FixedTrait::from_unscaled_felt(18), 'result[1] = 18'); + assert((*result.data[2]).into() == FixedTrait::from_unscaled_felt(21), 'result[2] = 21'); + assert(result.data.len() == 3, 'data len is 3'); + assert(result.shape.len() == 1, 'shape len is 1'); +} + diff --git a/src/tests/operators/linalg/matmul_test.cairo b/src/tests/operators/linalg/matmul/matmul_i32_test.cairo similarity index 93% rename from src/tests/operators/linalg/matmul_test.cairo rename to src/tests/operators/linalg/matmul/matmul_i32_test.cairo index 17ee35cec..5e1ebb846 100644 --- a/src/tests/operators/linalg/matmul_test.cairo +++ b/src/tests/operators/linalg/matmul/matmul_i32_test.cairo @@ -10,7 +10,7 @@ use orion::tests::helpers::tensor::i32::{ #[test] #[available_gas(200000000)] -fn tensor_matmul() { +fn matmul_1Dx1D() { //! Case: Dot product (1D x 1D) let tensor_1 = i32_tensor_1x3_helper(); let tensor_2 = i32_tensor_1x3_helper(); @@ -19,7 +19,11 @@ fn tensor_matmul() { assert((*result.data[0]).into() == 5, 'result[0] = 5'); assert(result.data.len() == 1, 'data len is 1'); assert(result.shape.len() == 1, 'shape len is 1'); +} +#[test] +#[available_gas(200000000)] +fn matmul_2Dx2D() { //! Case: Matrix multiplication (2D x 2D) let tensor_1 = i32_tensor_2x2_helper(); let tensor_2 = i32_tensor_2x2_helper(); @@ -35,7 +39,7 @@ fn tensor_matmul() { #[test] #[available_gas(200000000)] -fn tensor_matmul_with_matrix_vec() { +fn matmul_2Dx1D() { //! Case: Matrix-Vector multiplication (2D x 1D) let tensor_1 = i32_tensor_3x3_helper(); let tensor_2 = i32_tensor_1x3_helper(); @@ -46,7 +50,11 @@ fn tensor_matmul_with_matrix_vec() { assert((*result.data[2]).into() == 23, 'result[2] = 23'); assert(result.data.len() == 3, 'data len is 3'); assert(result.shape.len() == 1, 'shape len is 1'); +} +#[test] +#[available_gas(200000000)] +fn matmul_1Dx2D() { //! Case: Matrix-Vector multiplication (1D x 2D) let tensor_1 = i32_tensor_1x3_helper(); let tensor_2 = i32_tensor_3x3_helper(); diff --git a/src/tests/operators/linalg/matmul/matmul_u32_test.cairo b/src/tests/operators/linalg/matmul/matmul_u32_test.cairo new file mode 100644 index 000000000..62196a0c9 --- /dev/null +++ b/src/tests/operators/linalg/matmul/matmul_u32_test.cairo @@ -0,0 +1,68 @@ +use array::ArrayTrait; +use array::SpanTrait; +use traits::Into; + +use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::core::TensorTrait; +use orion::tests::helpers::tensor::u32::{ + u32_tensor_1x3_helper, u32_tensor_2x2_helper, u32_tensor_3x3_helper +}; + +#[test] +#[available_gas(200000000)] +fn matmul_1Dx1D() { + //! Case: Dot product (1D x 1D) + let tensor_1 = u32_tensor_1x3_helper(); + let tensor_2 = u32_tensor_1x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == 5, 'result[0] = 5'); + assert(result.data.len() == 1, 'data len is 1'); + assert(result.shape.len() == 1, 'shape len is 1'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_2Dx2D() { + //! Case: Matrix multiplication (2D x 2D) + let tensor_1 = u32_tensor_2x2_helper(); + let tensor_2 = u32_tensor_2x2_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 6, 'result[2] = 6'); + assert((*result.data[3]).into() == 11, 'result[3] = 11'); + assert(result.data.len() == 4, 'data len is 4'); + assert(result.shape.len() == 2, 'shape len is 2'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_2Dx1D() { + //! Case: Matrix-Vector multiplication (2D x 1D) + let tensor_1 = u32_tensor_3x3_helper(); + let tensor_2 = u32_tensor_1x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == 5, 'result[0] = 5'); + assert((*result.data[1]).into() == 14, 'result[1] = 14'); + assert((*result.data[2]).into() == 23, 'result[2] = 23'); + assert(result.data.len() == 3, 'data len is 3'); + assert(result.shape.len() == 1, 'shape len is 1'); +} + +#[test] +#[available_gas(200000000)] +fn matmul_1Dx2D() { + //! Case: Matrix-Vector multiplication (1D x 2D) + let tensor_1 = u32_tensor_1x3_helper(); + let tensor_2 = u32_tensor_3x3_helper(); + + let result = tensor_1.matmul(@tensor_2); + assert((*result.data[0]).into() == 15, 'result[0] = 15'); + assert((*result.data[1]).into() == 18, 'result[1] = 18'); + assert((*result.data[2]).into() == 21, 'result[2] = 21'); + assert(result.data.len() == 3, 'data len is 3'); + assert(result.shape.len() == 1, 'shape len is 1'); +} From 755f8613c6f8601b709c58db86a9f854c4d1e0c2 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Mon, 19 Jun 2023 13:39:09 +0300 Subject: [PATCH 008/126] refactor tensor abs tests --- src/tests/operators/math/abs.cairo | 2 +- .../operators/math/abs/abs_fp_test.cairo | 49 +------- .../abs/abs_fp_test/abs_fp16x16_test.cairo | 78 +++++++++++++ .../abs/abs_fp_test/abs_fp8x23_test.cairo | 78 +++++++++++++ .../operators/math/abs/abs_i32_test.cairo | 108 +++++++++++------- .../operators/math/abs/abs_u32_test.cairo | 90 +++++++++------ 6 files changed, 280 insertions(+), 125 deletions(-) create mode 100644 src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo create mode 100644 src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo diff --git a/src/tests/operators/math/abs.cairo b/src/tests/operators/math/abs.cairo index 14db157fe..2e9851d53 100644 --- a/src/tests/operators/math/abs.cairo +++ b/src/tests/operators/math/abs.cairo @@ -1,3 +1,3 @@ mod abs_i32_test; mod abs_u32_test; -mod abs_fp_test; \ No newline at end of file +mod abs_fp_test; diff --git a/src/tests/operators/math/abs/abs_fp_test.cairo b/src/tests/operators/math/abs/abs_fp_test.cairo index 8ae1251bb..428e27106 100644 --- a/src/tests/operators/math/abs/abs_fp_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test.cairo @@ -1,47 +1,2 @@ -use array::SpanTrait; -use array::ArrayTrait; -use option::OptionTrait; - -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; - -#[test] -#[available_gas(2000000)] -fn tensor_abs_fp() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, true)); - arr.append(FixedTrait::new(1, true)); - arr.append(FixedTrait::new(2, false)); - arr.append(FixedTrait::new(3, false)); - arr.append(FixedTrait::new(4, true)); - arr.append(FixedTrait::new(5, false)); - arr.append(FixedTrait::new(6, false)); - arr.append(FixedTrait::new(7, true)); - arr.append(FixedTrait::new(8, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor = TensorTrait::::new( - sizes.span(), arr.span(), Option::Some(extra) - ); - - let result = tensor.abs(); - assert(*result.data.at(0) == FixedTrait::new(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new(1, false), 'result[1] = 1'); - assert(*result.data.at(2) == FixedTrait::new(2, false), 'result[2] = 2'); - assert(*result.data.at(3) == FixedTrait::new(3, false), 'result[3] = 3'); - assert(*result.data.at(4) == FixedTrait::new(4, false), 'result[4] = 4'); - assert(*result.data.at(5) == FixedTrait::new(5, false), 'result[5] = 5'); - assert(*result.data.at(6) == FixedTrait::new(6, false), 'result[6] = 6'); - assert(*result.data.at(7) == FixedTrait::new(7, false), 'result[7] = 7'); - assert(*result.data.at(8) == FixedTrait::new(8, false), 'result[8] = 8'); - - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); -} - +mod abs_fp8x23_test; +mod abs_fp16x16_test; diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo b/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo new file mode 100644 index 000000000..2339cfa40 --- /dev/null +++ b/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo @@ -0,0 +1,78 @@ +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16; + + #[test] + #[available_gas(2000000000)] + fn abs_1D() { + let tensor = fp_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); + } +} + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16; + + + #[test] + #[available_gas(2000000000)] + fn abs_2D() { + let tensor = fp_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + } +} + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + use core::option::OptionTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16; + + + #[test] + #[available_gas(2000000000)] + fn abs_3D() { + let tensor = fp_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); + assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + } +} diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo b/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo new file mode 100644 index 000000000..4edcfd172 --- /dev/null +++ b/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo @@ -0,0 +1,78 @@ +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23; + + #[test] + #[available_gas(2000000000)] + fn abs_1D() { + let tensor = fp_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); + } +} + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23; + + + #[test] + #[available_gas(2000000000)] + fn abs_2D() { + let tensor = fp_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + } +} + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + use core::option::OptionTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23; + + + #[test] + #[available_gas(2000000000)] + fn abs_3D() { + let tensor = fp_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); + assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + } +} diff --git a/src/tests/operators/math/abs/abs_i32_test.cairo b/src/tests/operators/math/abs/abs_i32_test.cairo index 11e72d72a..32f27a99d 100644 --- a/src/tests/operators/math/abs/abs_i32_test.cairo +++ b/src/tests/operators/math/abs/abs_i32_test.cairo @@ -1,45 +1,67 @@ -use array::SpanTrait; -use array::ArrayTrait; -use option::OptionTrait; - -use orion::operators::tensor::implementations::impl_tensor_i32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; - - -#[test] -#[available_gas(2000000)] -fn tensor_abs_i32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr = ArrayTrait::::new(); - arr.append(IntegerTrait::new(0, true)); - arr.append(IntegerTrait::new(1, true)); - arr.append(IntegerTrait::new(2, false)); - arr.append(IntegerTrait::new(3, false)); - arr.append(IntegerTrait::new(4, true)); - arr.append(IntegerTrait::new(5, false)); - arr.append(IntegerTrait::new(6, false)); - arr.append(IntegerTrait::new(7, true)); - arr.append(IntegerTrait::new(8, false)); - - let extra = Option::::None(()); - - let tensor = TensorTrait::::new(sizes.span(), arr.span(), extra); - - let result = tensor.abs(); - assert(*result.data.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); - assert(*result.data.at(2) == IntegerTrait::new(2, false), 'result[2] = 2'); - assert(*result.data.at(3) == IntegerTrait::new(3, false), 'result[3] = 3'); - assert(*result.data.at(4) == IntegerTrait::new(4, false), 'result[4] = 4'); - assert(*result.data.at(5) == IntegerTrait::new(5, false), 'result[5] = 5'); - assert(*result.data.at(6) == IntegerTrait::new(6, false), 'result[6] = 6'); - assert(*result.data.at(7) == IntegerTrait::new(7, false), 'result[7] = 7'); - assert(*result.data.at(8) == IntegerTrait::new(8, false), 'result[8] = 8'); - - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_neg_helper; + + #[test] + #[available_gas(2000000000)] + fn abs_1D() { + let tensor = i32_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + } +} + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_neg_helper; + + #[test] + #[available_gas(2000000000)] + fn abs_2D() { + let tensor = i32_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + } +} + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + use core::option::OptionTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_neg_helper; + + #[test] + #[available_gas(2000000000)] + fn abs_3D() { + let tensor = i32_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + } } diff --git a/src/tests/operators/math/abs/abs_u32_test.cairo b/src/tests/operators/math/abs/abs_u32_test.cairo index c314f9fe9..94ac6ae3b 100644 --- a/src/tests/operators/math/abs/abs_u32_test.cairo +++ b/src/tests/operators/math/abs/abs_u32_test.cairo @@ -1,41 +1,63 @@ -use array::SpanTrait; -use array::ArrayTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; -#[test] -#[available_gas(2000000)] -fn tensor_abs_u32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); + #[test] + #[available_gas(20000000)] + fn abs_1D() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + } +} - let mut arr = ArrayTrait::::new(); - arr.append(0); - arr.append(1); - arr.append(2); - arr.append(3); - arr.append(4); - arr.append(5); - arr.append(6); - arr.append(7); - arr.append(8); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; - let extra = Option::::None(()); + #[test] + #[available_gas(20000000)] + fn abs_2D() { + let tensor = u32_tensor_2x2_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + } +} - let tensor = TensorTrait::::new(sizes.span(), arr.span(), extra); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; - let result = tensor.abs(); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 2, 'result[2] = 2'); - assert(*result.data.at(3) == 3, 'result[3] = 3'); - assert(*result.data.at(4) == 4, 'result[4] = 4'); - assert(*result.data.at(5) == 5, 'result[5] = 5'); - assert(*result.data.at(6) == 6, 'result[6] = 6'); - assert(*result.data.at(7) == 7, 'result[7] = 7'); - assert(*result.data.at(8) == 8, 'result[8] = 8'); - - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + #[test] + #[available_gas(20000000)] + fn abs_3D() { + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + assert(*result.data[4] == 4, 'result[4] = 4'); + assert(*result.data[5] == 5, 'result[5] = 5'); + assert(*result.data[6] == 6, 'result[6] = 6'); + assert(*result.data[7] == 7, 'result[7] = 7'); + } } From 7f87651e7c3e84c3074f6d683ddb202ccb114c8a Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Mon, 19 Jun 2023 13:43:23 +0300 Subject: [PATCH 009/126] rename mod in argmax/argmin tests --- .../math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo | 6 +++--- .../math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo | 6 +++--- src/tests/operators/math/argmax/argmax_i32_test.cairo | 6 +++--- src/tests/operators/math/argmax/argmax_u32_test.cairo | 6 +++--- .../math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo | 6 +++--- .../math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo | 6 +++--- src/tests/operators/math/argmin/argmin_i32_test.cairo | 6 +++--- src/tests/operators/math/argmin/argmin_u32_test.cairo | 6 +++--- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo index 918c81c19..178d48286 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D { +mod tensor_1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; @@ -111,7 +111,7 @@ mod tensor1D { } #[cfg(test)] -mod tensor2D { +mod tensor_2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; @@ -201,7 +201,7 @@ mod tensor2D { } #[cfg(test)] -mod tensor3D { +mod tensor_3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo index 15026a3be..011793fd9 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D { +mod tensor_1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; @@ -111,7 +111,7 @@ mod tensor1D { } #[cfg(test)] -mod tensor2D { +mod tensor_2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; @@ -201,7 +201,7 @@ mod tensor2D { } #[cfg(test)] -mod tensor3D { +mod tensor_3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; diff --git a/src/tests/operators/math/argmax/argmax_i32_test.cairo b/src/tests/operators/math/argmax/argmax_i32_test.cairo index 28ba322cb..ec68129bf 100644 --- a/src/tests/operators/math/argmax/argmax_i32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_i32_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D { +mod tensor_1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -109,7 +109,7 @@ mod tensor1D { } #[cfg(test)] -mod tensor2D { +mod tensor_2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -195,7 +195,7 @@ mod tensor2D { } #[cfg(test)] -mod tensor3D { +mod tensor_3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; diff --git a/src/tests/operators/math/argmax/argmax_u32_test.cairo b/src/tests/operators/math/argmax/argmax_u32_test.cairo index 7728a140a..35b77a39f 100644 --- a/src/tests/operators/math/argmax/argmax_u32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_u32_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D { +mod tensor_1D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -95,7 +95,7 @@ mod tensor1D { } #[cfg(test)] -mod tensor2D { +mod tensor_2D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -180,7 +180,7 @@ mod tensor2D { } #[cfg(test)] -mod tensor3D { +mod tensor_3D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo index 6abd8b3af..fa528ca67 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D { +mod tensor_1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; @@ -119,7 +119,7 @@ mod tensor1D { } #[cfg(test)] -mod tensor2D { +mod tensor_2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; @@ -220,7 +220,7 @@ mod tensor2D { } #[cfg(test)] -mod tensor3D { +mod tensor_3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_16x16; diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo index 2677a83fb..403377129 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D { +mod tensor_1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; @@ -119,7 +119,7 @@ mod tensor1D { } #[cfg(test)] -mod tensor2D { +mod tensor_2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; @@ -220,7 +220,7 @@ mod tensor2D { } #[cfg(test)] -mod tensor3D { +mod tensor_3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::implementations::impl_8x23; diff --git a/src/tests/operators/math/argmin/argmin_i32_test.cairo b/src/tests/operators/math/argmin/argmin_i32_test.cairo index 003d85555..33eedc8a5 100644 --- a/src/tests/operators/math/argmin/argmin_i32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_i32_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D { +mod tensor_1D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -118,7 +118,7 @@ mod tensor1D { } #[cfg(test)] -mod tensor2D { +mod tensor_2D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; @@ -216,7 +216,7 @@ mod tensor2D { } #[cfg(test)] -mod tensor3D { +mod tensor_3D { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::implementations::impl_tensor_i32; diff --git a/src/tests/operators/math/argmin/argmin_u32_test.cairo b/src/tests/operators/math/argmin/argmin_u32_test.cairo index ff024cf1b..04c05080c 100644 --- a/src/tests/operators/math/argmin/argmin_u32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_u32_test.cairo @@ -1,6 +1,6 @@ #[cfg(test)] -mod tensor1D { +mod tensor_1D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -104,7 +104,7 @@ mod tensor1D { } #[cfg(test)] -mod tensor2D { +mod tensor_2D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -201,7 +201,7 @@ mod tensor2D { } #[cfg(test)] -mod tensor3D { +mod tensor_3D { use array::{ArrayTrait,SpanTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; From 074bed70bcfe273c856afa582cb9339b4fb76df5 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Mon, 19 Jun 2023 16:22:06 +0300 Subject: [PATCH 010/126] refactor tensor ceil tests --- src/tests/helpers/tensor/i32.cairo | 204 +++++++++--------- .../operators/math/abs/abs_i32_test.cairo | 106 ++++----- .../operators/math/ceil/ceil_fp_test.cairo | 38 +--- .../ceil/ceil_fp_test/ceil_fp16x16_test.cairo | 109 ++++++++++ .../ceil/ceil_fp_test/ceil_fp8x23_test.cairo | 109 ++++++++++ .../operators/math/ceil/ceil_i32_test.cairo | 62 +++--- .../operators/math/ceil/ceil_u32_test.cairo | 98 +++++---- 7 files changed, 450 insertions(+), 276 deletions(-) create mode 100644 src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo create mode 100644 src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo diff --git a/src/tests/helpers/tensor/i32.cairo b/src/tests/helpers/tensor/i32.cairo index d9bd95da3..b01ce5a3e 100644 --- a/src/tests/helpers/tensor/i32.cairo +++ b/src/tests/helpers/tensor/i32.cairo @@ -12,9 +12,9 @@ fn i32_tensor_1x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: false }); + data.append(i32 { mag: 2, sign: false }); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -27,9 +27,9 @@ fn i32_tensor_1x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(2_u32, true)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: true }); + data.append(i32 { mag: 2, sign: true }); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -45,10 +45,10 @@ fn i32_tensor_2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: false }); + data.append(i32 { mag: 2, sign: false }); + data.append(i32 { mag: 3, sign: false }); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -62,10 +62,10 @@ fn i32_tensor_2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(2_u32, true)); - data.append(IntegerTrait::new(3_u32, true)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: true }); + data.append(i32 { mag: 2, sign: true }); + data.append(i32 { mag: 3, sign: true }); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -79,15 +79,15 @@ fn i32_tensor_3x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); - data.append(IntegerTrait::new(6_u32, false)); - data.append(IntegerTrait::new(7_u32, false)); - data.append(IntegerTrait::new(8_u32, false)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: false }); + data.append(i32 { mag: 2, sign: false }); + data.append(i32 { mag: 3, sign: false }); + data.append(i32 { mag: 4, sign: false }); + data.append(i32 { mag: 5, sign: false }); + data.append(i32 { mag: 6, sign: false }); + data.append(i32 { mag: 7, sign: false }); + data.append(i32 { mag: 8, sign: false }); let extra = Option::::None(()); @@ -102,15 +102,15 @@ fn i32_tensor_3x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(2_u32, true)); - data.append(IntegerTrait::new(3_u32, true)); - data.append(IntegerTrait::new(4_u32, true)); - data.append(IntegerTrait::new(5_u32, true)); - data.append(IntegerTrait::new(6_u32, true)); - data.append(IntegerTrait::new(7_u32, true)); - data.append(IntegerTrait::new(8_u32, true)); + data.append(i32 { mag: 0_u32, sign: false }); + data.append(i32 { mag: 1_u32, sign: true }); + data.append(i32 { mag: 2_u32, sign: true }); + data.append(i32 { mag: 3_u32, sign: true }); + data.append(i32 { mag: 4_u32, sign: true }); + data.append(i32 { mag: 5_u32, sign: true }); + data.append(i32 { mag: 6_u32, sign: true }); + data.append(i32 { mag: 7_u32, sign: true }); + data.append(i32 { mag: 8_u32, sign: true }); let extra = Option::::None(()); @@ -125,12 +125,12 @@ fn i32_tensor_3x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: false }); + data.append(i32 { mag: 2, sign: false }); + data.append(i32 { mag: 3, sign: false }); + data.append(i32 { mag: 4, sign: false }); + data.append(i32 { mag: 5, sign: false }); let extra = Option::::None(()); @@ -145,12 +145,12 @@ fn i32_tensor_3x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(2_u32, true)); - data.append(IntegerTrait::new(3_u32, true)); - data.append(IntegerTrait::new(4_u32, true)); - data.append(IntegerTrait::new(5_u32, true)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: true }); + data.append(i32 { mag: 2, sign: true }); + data.append(i32 { mag: 3, sign: true }); + data.append(i32 { mag: 4, sign: true }); + data.append(i32 { mag: 5, sign: true }); let extra = Option::::None(()); @@ -165,9 +165,9 @@ fn i32_tensor_3x1_helper() -> Tensor { sizes.append(1); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: false }); + data.append(i32 { mag: 2, sign: false }); let extra = Option::::None(()); @@ -182,9 +182,9 @@ fn i32_tensor_3x1_neg_helper() -> Tensor { sizes.append(1); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(2_u32, true)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: true }); + data.append(i32 { mag: 2, sign: true }); let extra = Option::::None(()); @@ -199,12 +199,12 @@ fn i32_tensor_2x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: false }); + data.append(i32 { mag: 2, sign: false }); + data.append(i32 { mag: 3, sign: false }); + data.append(i32 { mag: 4, sign: false }); + data.append(i32 { mag: 5, sign: false }); let extra = Option::::None(()); @@ -219,12 +219,12 @@ fn i32_tensor_2x3_neg_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(2_u32, true)); - data.append(IntegerTrait::new(3_u32, true)); - data.append(IntegerTrait::new(4_u32, true)); - data.append(IntegerTrait::new(5_u32, true)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: true }); + data.append(i32 { mag: 2, sign: true }); + data.append(i32 { mag: 3, sign: true }); + data.append(i32 { mag: 4, sign: true }); + data.append(i32 { mag: 5, sign: true }); let extra = Option::::None(()); @@ -242,14 +242,14 @@ fn i32_tensor_2x2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); - data.append(IntegerTrait::new(6_u32, false)); - data.append(IntegerTrait::new(7_u32, false)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: false }); + data.append(i32 { mag: 2, sign: false }); + data.append(i32 { mag: 3, sign: false }); + data.append(i32 { mag: 4, sign: false }); + data.append(i32 { mag: 5, sign: false }); + data.append(i32 { mag: 6, sign: false }); + data.append(i32 { mag: 7, sign: false }); let extra = Option::::None(()); @@ -265,14 +265,14 @@ fn i32_tensor_2x2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(2_u32, true)); - data.append(IntegerTrait::new(3_u32, true)); - data.append(IntegerTrait::new(4_u32, true)); - data.append(IntegerTrait::new(5_u32, true)); - data.append(IntegerTrait::new(6_u32, true)); - data.append(IntegerTrait::new(7_u32, true)); + data.append(i32 { mag: 0_u32, sign: false }); + data.append(i32 { mag: 1_u32, sign: true }); + data.append(i32 { mag: 2_u32, sign: true }); + data.append(i32 { mag: 3_u32, sign: true }); + data.append(i32 { mag: 4_u32, sign: true }); + data.append(i32 { mag: 5_u32, sign: true }); + data.append(i32 { mag: 6_u32, sign: true }); + data.append(i32 { mag: 7_u32, sign: true }); let extra = Option::::None(()); @@ -288,18 +288,18 @@ fn i32_tensor_3x2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); - data.append(IntegerTrait::new(6_u32, false)); - data.append(IntegerTrait::new(7_u32, false)); - data.append(IntegerTrait::new(8_u32, false)); - data.append(IntegerTrait::new(9_u32, false)); - data.append(IntegerTrait::new(10_u32, false)); - data.append(IntegerTrait::new(11_u32, false)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: false }); + data.append(i32 { mag: 2, sign: false }); + data.append(i32 { mag: 3, sign: false }); + data.append(i32 { mag: 4, sign: false }); + data.append(i32 { mag: 5, sign: false }); + data.append(i32 { mag: 6, sign: false }); + data.append(i32 { mag: 7, sign: false }); + data.append(i32 { mag: 8, sign: false }); + data.append(i32 { mag: 9, sign: false }); + data.append(i32 { mag: 10, sign: false }); + data.append(i32 { mag: 11, sign: false }); let extra = Option::::None(()); @@ -315,18 +315,18 @@ fn i32_tensor_3x2x2_neg_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(2_u32, true)); - data.append(IntegerTrait::new(3_u32, true)); - data.append(IntegerTrait::new(4_u32, true)); - data.append(IntegerTrait::new(5_u32, true)); - data.append(IntegerTrait::new(6_u32, true)); - data.append(IntegerTrait::new(7_u32, true)); - data.append(IntegerTrait::new(8_u32, true)); - data.append(IntegerTrait::new(9_u32, true)); - data.append(IntegerTrait::new(10_u32, true)); - data.append(IntegerTrait::new(11_u32, true)); + data.append(i32 { mag: 0, sign: false }); + data.append(i32 { mag: 1, sign: true }); + data.append(i32 { mag: 2, sign: true }); + data.append(i32 { mag: 3, sign: true }); + data.append(i32 { mag: 4, sign: true }); + data.append(i32 { mag: 5, sign: true }); + data.append(i32 { mag: 6, sign: true }); + data.append(i32 { mag: 7, sign: true }); + data.append(i32 { mag: 8, sign: true }); + data.append(i32 { mag: 9, sign: true }); + data.append(i32 { mag: 10, sign: true }); + data.append(i32 { mag: 11, sign: true }); let extra = Option::::None(()); diff --git a/src/tests/operators/math/abs/abs_i32_test.cairo b/src/tests/operators/math/abs/abs_i32_test.cairo index 32f27a99d..603c5c39f 100644 --- a/src/tests/operators/math/abs/abs_i32_test.cairo +++ b/src/tests/operators/math/abs/abs_i32_test.cairo @@ -1,67 +1,41 @@ -#[cfg(test)] -mod tensor_1D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - - use orion::operators::tensor::implementations::impl_tensor_i32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::i32::i32_tensor_1x3_neg_helper; - - #[test] - #[available_gas(2000000000)] - fn abs_1D() { - let tensor = i32_tensor_1x3_neg_helper(); - let result = tensor.abs(); - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 1, 'result[1] = 1'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - } -} - -#[cfg(test)] -mod tensor_2D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - - use orion::operators::tensor::implementations::impl_tensor_i32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::i32::i32_tensor_2x2_neg_helper; - - #[test] - #[available_gas(2000000000)] - fn abs_2D() { - let tensor = i32_tensor_2x2_neg_helper(); - let result = tensor.abs(); - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 1, 'result[1] = 1'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - assert((*result.data[3]).into() == 3, 'result[3] = 3'); - } +use array::SpanTrait; +use array::ArrayTrait; +use core::traits::Into; + +use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::tests::helpers::tensor::i32::i32_tensor_1x3_neg_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2_neg_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_neg_helper; + + +#[test] +#[available_gas(2000000000000000000)] +fn tensor_abs() { + // 1D + let tensor = i32_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + + // 2D + let tensor = i32_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + + // 3D + let tensor = i32_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); } - -#[cfg(test)] -mod tensor_3D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - use core::option::OptionTrait; - - use orion::operators::tensor::implementations::impl_tensor_i32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_neg_helper; - - #[test] - #[available_gas(2000000000)] - fn abs_3D() { - let tensor = i32_tensor_2x2x2_neg_helper(); - let result = tensor.abs(); - - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - assert((*result.data[3]).into() == 3, 'result[3] = 3'); - assert((*result.data[7]).into() == 7, 'result[7] = 7'); - } -} - diff --git a/src/tests/operators/math/ceil/ceil_fp_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test.cairo index ceffe77f0..957307977 100644 --- a/src/tests/operators/math/ceil/ceil_fp_test.cairo +++ b/src/tests/operators/math/ceil/ceil_fp_test.cairo @@ -1,36 +1,2 @@ -use array::SpanTrait; -use array::ArrayTrait; -use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; - - -#[test] -#[available_gas(2000000)] -fn tensor_ceil_fp() { - let mut sizes = ArrayTrait::new(); - sizes.append(1); - sizes.append(4); - - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(30000, false)); // 0.00357627868 - arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 - arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor = TensorTrait::::new( - sizes.span(), arr.span(), Option::Some(extra) - ); - - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 8388608'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false),'result[2] = 100663296'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -92274688'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); -} - +mod ceil_fp8x23_test; +mod ceil_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo new file mode 100644 index 000000000..137d25c6e --- /dev/null +++ b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo @@ -0,0 +1,109 @@ +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use option::OptionTrait; + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16; + + #[test] + #[available_gas(2000000)] + fn ceil_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } +} + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use option::OptionTrait; + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16; + + #[test] + #[available_gas(2000000)] + fn ceil_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } +} + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use option::OptionTrait; + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16; + + #[test] + #[available_gas(2000000)] + fn ceil_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + arr.append(FixedTrait::new(32768, false)); // 0.5 + arr.append(FixedTrait::new(32768, true)); // - 0.5 + arr.append(FixedTrait::new(98304, false)); // 1.5 + arr.append(FixedTrait::new(98304, true)); // - 1.5 + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } +} + diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo new file mode 100644 index 000000000..6beb19a06 --- /dev/null +++ b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo @@ -0,0 +1,109 @@ +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use option::OptionTrait; + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23; + + #[test] + #[available_gas(2000000)] + fn ceil_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } +} + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use option::OptionTrait; + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23; + + #[test] + #[available_gas(2000000)] + fn ceil_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } +} + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use option::OptionTrait; + use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23; + + #[test] + #[available_gas(2000000)] + fn ceil_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + arr.append(FixedTrait::new(4194304, false)); // 0.5 + arr.append(FixedTrait::new(4194304, true)); // - 0.5 + arr.append(FixedTrait::new(12582912, false)); // 1.5 + arr.append(FixedTrait::new(12582912, true)); // - 1.5 + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } +} + diff --git a/src/tests/operators/math/ceil/ceil_i32_test.cairo b/src/tests/operators/math/ceil/ceil_i32_test.cairo index e3dad68d7..40da59442 100644 --- a/src/tests/operators/math/ceil/ceil_i32_test.cairo +++ b/src/tests/operators/math/ceil/ceil_i32_test.cairo @@ -1,45 +1,41 @@ use array::SpanTrait; use array::ArrayTrait; -use option::OptionTrait; +use core::traits::Into; use orion::operators::tensor::implementations::impl_tensor_i32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; +use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; #[test] -#[available_gas(2000000)] -fn tensor_ceil_i32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr = ArrayTrait::::new(); - arr.append(IntegerTrait::new(0, false)); - arr.append(IntegerTrait::new(1, true)); - arr.append(IntegerTrait::new(2, false)); - arr.append(IntegerTrait::new(3, false)); - arr.append(IntegerTrait::new(4, true)); - arr.append(IntegerTrait::new(5, false)); - arr.append(IntegerTrait::new(6, false)); - arr.append(IntegerTrait::new(7, true)); - arr.append(IntegerTrait::new(8, false)); - - let extra = Option::::None(()); - - let tensor = TensorTrait::::new(sizes.span(), arr.span(), extra); +#[available_gas(2000000000000000000)] +fn tensor_ceil() { + // 1D + let tensor = i32_tensor_1x3_helper(); + let result = tensor.ceil(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + // 2D + let tensor = i32_tensor_2x2_helper(); let result = tensor.ceil(); - assert(*result.data.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == IntegerTrait::new(1, true), 'result[1] = -1'); - assert(*result.data.at(2) == IntegerTrait::new(2, false), 'result[2] = 2'); - assert(*result.data.at(3) == IntegerTrait::new(3, false), 'result[3] = 3'); - assert(*result.data.at(4) == IntegerTrait::new(4, true), 'result[4] = -4'); - assert(*result.data.at(5) == IntegerTrait::new(5, false), 'result[5] = 5'); - assert(*result.data.at(6) == IntegerTrait::new(6, false), 'result[6] = 6'); - assert(*result.data.at(7) == IntegerTrait::new(7, true), 'result[7] = -7'); - assert(*result.data.at(8) == IntegerTrait::new(8, false), 'result[8] = 8'); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + // 3D + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.ceil(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); } - diff --git a/src/tests/operators/math/ceil/ceil_u32_test.cairo b/src/tests/operators/math/ceil/ceil_u32_test.cairo index 7841802e0..36d72c333 100644 --- a/src/tests/operators/math/ceil/ceil_u32_test.cairo +++ b/src/tests/operators/math/ceil/ceil_u32_test.cairo @@ -1,43 +1,63 @@ -use array::SpanTrait; -use array::ArrayTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - - - -#[test] -#[available_gas(2000000)] -fn tensor_ceil_u32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr = ArrayTrait::::new(); - arr.append(0); - arr.append(1); - arr.append(2); - arr.append(3); - arr.append(4); - arr.append(5); - arr.append(6); - arr.append(7); - arr.append(8); - - let extra = Option::::None(()); +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn ceil_1D() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + } +} - let tensor = TensorTrait::::new(sizes.span(), arr.span(), extra); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn ceil_2D() { + let tensor = u32_tensor_2x2_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + } +} - let result = tensor.ceil(); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 2, 'result[2] = 2'); - assert(*result.data.at(3) == 3, 'result[3] = 3'); - assert(*result.data.at(4) == 4, 'result[4] = 4'); - assert(*result.data.at(5) == 5, 'result[5] = 5'); - assert(*result.data.at(6) == 6, 'result[6] = 6'); - assert(*result.data.at(7) == 7, 'result[7] = 7'); - assert(*result.data.at(8) == 8, 'result[8] = 8'); - - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(20000000)] + fn ceil_3D() { + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + assert(*result.data[4] == 4, 'result[4] = 4'); + assert(*result.data[5] == 5, 'result[5] = 5'); + assert(*result.data[6] == 6, 'result[6] = 6'); + assert(*result.data[7] == 7, 'result[7] = 7'); + } } From 08b0eb21c9c984a47397a6577b3e7b030439cc55 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 10:46:58 +0300 Subject: [PATCH 011/126] refactor tensor equal tests --- .../operators/math/equal/equal_fp_test.cairo | 122 +-------- .../equal_fp_test/equal_fp16x16_test.cairo | 258 ++++++++++++++++++ .../equal_fp_test/equal_fp8x23_test.cairo | 258 ++++++++++++++++++ .../operators/math/equal/equal_i32_test.cairo | 140 +++++++++- .../operators/math/equal/equal_u32_test.cairo | 141 +++++++++- 5 files changed, 795 insertions(+), 124 deletions(-) create mode 100644 src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo create mode 100644 src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo diff --git a/src/tests/operators/math/equal/equal_fp_test.cairo b/src/tests/operators/math/equal/equal_fp_test.cairo index 9d50ca91f..3ca100f21 100644 --- a/src/tests/operators/math/equal/equal_fp_test.cairo +++ b/src/tests/operators/math/equal/equal_fp_test.cairo @@ -1,120 +1,2 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; - -#[test] -#[available_gas(2000000)] -fn tensor_eq_fp() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(10, false)); - arr_2.append(FixedTrait::new(11, false)); - arr_2.append(FixedTrait::new(2, true)); - arr_2.append(FixedTrait::new(3, true)); - arr_2.append(FixedTrait::new(4, false)); - arr_2.append(FixedTrait::new(5, false)); - arr_2.append(FixedTrait::new(16, false)); - arr_2.append(FixedTrait::new(17, false)); - arr_2.append(FixedTrait::new(18, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_eq_fp_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - arr_1.append(FixedTrait::new(9, false)); - arr_1.append(FixedTrait::new(10, false)); - arr_1.append(FixedTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(0, false)); - arr_2.append(FixedTrait::new(1, false)); - arr_2.append(FixedTrait::new(2, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} +mod equal_fp8x23_test; +mod equal_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo b/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo new file mode 100644 index 000000000..af03a260b --- /dev/null +++ b/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo @@ -0,0 +1,258 @@ +use array::SpanTrait; +use array::{ArrayTrait}; + +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; +use orion::numbers::fixed_point::implementations::impl_16x16; + + +// ===== 1D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, true)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(12, false)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data.at(8) == 0, 'result[8] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000)] +fn tensor_eq_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data.at(9) == 0, 'result[9] = 0'); + assert(*result_b.data.at(10) == 0, 'result[10] = 0'); + assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(12, false)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000)] +fn tensor_eq_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo b/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo new file mode 100644 index 000000000..a2ad15dfe --- /dev/null +++ b/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo @@ -0,0 +1,258 @@ +use array::SpanTrait; +use array::{ArrayTrait}; + +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; +use orion::numbers::fixed_point::implementations::impl_8x23; + + +// ===== 1D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, true)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(12, false)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data.at(8) == 0, 'result[8] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000)] +fn tensor_eq_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data.at(9) == 0, 'result[9] = 0'); + assert(*result_b.data.at(10) == 0, 'result[10] = 0'); + assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(12, false)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000)] +fn tensor_eq_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} diff --git a/src/tests/operators/math/equal/equal_i32_test.cairo b/src/tests/operators/math/equal/equal_i32_test.cairo index 15dd13692..27950b114 100644 --- a/src/tests/operators/math/equal/equal_i32_test.cairo +++ b/src/tests/operators/math/equal/equal_i32_test.cairo @@ -5,9 +5,42 @@ use orion::operators::tensor::implementations::impl_tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +// ===== 1D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, true)); + arr_1.append(IntegerTrait::new(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + #[test] #[available_gas(2000000)] -fn tensor_eq_i32() { +fn tensor_eq_2D() { let mut sizes = ArrayTrait::new(); sizes.append(3); sizes.append(3); @@ -55,7 +88,7 @@ fn tensor_eq_i32() { #[test] #[available_gas(2000000)] -fn tensor_eq_i32_broadcast() { +fn tensor_eq_broadcast_2D() { let mut sizes_1 = ArrayTrait::new(); sizes_1.append(4); sizes_1.append(3); @@ -118,3 +151,106 @@ fn tensor_eq_i32_broadcast() { assert(*result_b.data.at(11) == 0, 'result[11] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(12, false)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000)] +fn tensor_eq_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} diff --git a/src/tests/operators/math/equal/equal_u32_test.cairo b/src/tests/operators/math/equal/equal_u32_test.cairo index 8f4dae6b9..ef15e9069 100644 --- a/src/tests/operators/math/equal/equal_u32_test.cairo +++ b/src/tests/operators/math/equal/equal_u32_test.cairo @@ -3,9 +3,42 @@ use array::{ArrayTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +// ===== 1D ===== // + #[test] #[available_gas(2000000)] -fn tensor_eq_u32() { +fn tensor_eq_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 1, 'result[2] = 1'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_2D() { let mut sizes = ArrayTrait::new(); sizes.append(3); sizes.append(3); @@ -53,7 +86,7 @@ fn tensor_eq_u32() { #[test] #[available_gas(2000000)] -fn tensor_eq_u32_broadcast() { +fn tensor_eq_broadcast_2D() { let mut sizes_1 = ArrayTrait::new(); sizes_1.append(4); sizes_1.append(3); @@ -116,3 +149,107 @@ fn tensor_eq_u32_broadcast() { assert(*result_b.data.at(11) == 0, 'result[11] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_eq_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0_u32); + arr_1.append(1_u32); + arr_1.append(2_u32); + arr_1.append(3_u32); + arr_1.append(4_u32); + arr_1.append(5_u32); + arr_1.append(6_u32); + arr_1.append(7_u32); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10_u32); + arr_2.append(11_u32); + arr_2.append(12_u32); + arr_2.append(13_u32); + arr_2.append(4_u32); + arr_2.append(5_u32); + arr_2.append(16_u32); + arr_2.append(17_u32); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000)] +fn tensor_eq_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0_u32); + arr_1.append(1_u32); + arr_1.append(2_u32); + arr_1.append(3_u32); + arr_1.append(4_u32); + arr_1.append(5_u32); + arr_1.append(6_u32); + arr_1.append(7_u32); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0_u32); + arr_2.append(1_u32); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + From 4e91b23baacfabb6060e079ad06e7a0057904de0 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 11:01:47 +0300 Subject: [PATCH 012/126] remove mod --- .../abs/abs_fp_test/abs_fp16x16_test.cairo | 124 ++++++------- .../abs/abs_fp_test/abs_fp8x23_test.cairo | 124 ++++++------- .../operators/math/abs/abs_i32_test.cairo | 9 +- .../operators/math/abs/abs_u32_test.cairo | 95 +++++----- .../ceil/ceil_fp_test/ceil_fp16x16_test.cairo | 171 ++++++++---------- .../ceil/ceil_fp_test/ceil_fp8x23_test.cairo | 171 ++++++++---------- .../operators/math/ceil/ceil_i32_test.cairo | 10 +- .../operators/math/ceil/ceil_u32_test.cairo | 96 +++++----- 8 files changed, 348 insertions(+), 452 deletions(-) diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo b/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo index 2339cfa40..a22ca9bd3 100644 --- a/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo @@ -1,78 +1,56 @@ -#[cfg(test)] -mod tensor_1D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_neg_helper; - use orion::numbers::fixed_point::core::{FixedTrait}; - use orion::numbers::fixed_point::implementations::impl_16x16; - - #[test] - #[available_gas(2000000000)] - fn abs_1D() { - let tensor = fp_tensor_1x3_neg_helper(); - let result = tensor.abs(); - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); - } +use array::SpanTrait; +use array::ArrayTrait; +use core::traits::Into; + +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::tests::helpers::tensor::fixed_point::fp16x16::{ + fp_tensor_1x3_neg_helper, fp_tensor_2x2_neg_helper, fp_tensor_2x2x2_neg_helper +}; +use orion::numbers::fixed_point::core::{FixedTrait}; +use orion::numbers::fixed_point::implementations::impl_16x16; + + +// ===== 1D ===== // + +#[test] +#[available_gas(2000000000)] +fn abs_1D() { + let tensor = fp_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); } -#[cfg(test)] -mod tensor_2D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_neg_helper; - use orion::numbers::fixed_point::core::{FixedTrait}; - use orion::numbers::fixed_point::implementations::impl_16x16; - - - #[test] - #[available_gas(2000000000)] - fn abs_2D() { - let tensor = fp_tensor_2x2_neg_helper(); - let result = tensor.abs(); - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - } +// ===== 2D ===== // + +#[test] +#[available_gas(2000000000)] +fn abs_2D() { + let tensor = fp_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); } -#[cfg(test)] -mod tensor_3D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - use core::option::OptionTrait; - - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_neg_helper; - use orion::numbers::fixed_point::core::{FixedTrait}; - use orion::numbers::fixed_point::implementations::impl_16x16; - - - #[test] - #[available_gas(2000000000)] - fn abs_3D() { - let tensor = fp_tensor_2x2x2_neg_helper(); - let result = tensor.abs(); - - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); - assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); - } +// ===== 3D ===== // + +#[test] +#[available_gas(2000000000)] +fn abs_3D() { + let tensor = fp_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); + assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); } + diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo b/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo index 4edcfd172..1900f6018 100644 --- a/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo @@ -1,78 +1,56 @@ -#[cfg(test)] -mod tensor_1D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_neg_helper; - use orion::numbers::fixed_point::core::{FixedTrait}; - use orion::numbers::fixed_point::implementations::impl_8x23; - - #[test] - #[available_gas(2000000000)] - fn abs_1D() { - let tensor = fp_tensor_1x3_neg_helper(); - let result = tensor.abs(); - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); - } +use array::SpanTrait; +use array::ArrayTrait; +use core::traits::Into; + +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::tests::helpers::tensor::fixed_point::fp8x23::{ + fp_tensor_1x3_neg_helper, fp_tensor_2x2_neg_helper, fp_tensor_2x2x2_neg_helper +}; +use orion::numbers::fixed_point::core::{FixedTrait}; +use orion::numbers::fixed_point::implementations::impl_8x23; + + +// ===== 1D ===== // + +#[test] +#[available_gas(2000000000)] +fn abs_1D() { + let tensor = fp_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); } -#[cfg(test)] -mod tensor_2D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_neg_helper; - use orion::numbers::fixed_point::core::{FixedTrait}; - use orion::numbers::fixed_point::implementations::impl_8x23; - - - #[test] - #[available_gas(2000000000)] - fn abs_2D() { - let tensor = fp_tensor_2x2_neg_helper(); - let result = tensor.abs(); - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - } +// ===== 2D ===== // + +#[test] +#[available_gas(2000000000)] +fn abs_2D() { + let tensor = fp_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); } -#[cfg(test)] -mod tensor_3D { - use array::SpanTrait; - use array::ArrayTrait; - use core::traits::Into; - use core::option::OptionTrait; - - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_neg_helper; - use orion::numbers::fixed_point::core::{FixedTrait}; - use orion::numbers::fixed_point::implementations::impl_8x23; - - - #[test] - #[available_gas(2000000000)] - fn abs_3D() { - let tensor = fp_tensor_2x2x2_neg_helper(); - let result = tensor.abs(); - - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); - assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); - } +// ===== 3D ===== // + +#[test] +#[available_gas(2000000000)] +fn abs_3D() { + let tensor = fp_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); + assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); } + diff --git a/src/tests/operators/math/abs/abs_i32_test.cairo b/src/tests/operators/math/abs/abs_i32_test.cairo index 603c5c39f..00c03ba9c 100644 --- a/src/tests/operators/math/abs/abs_i32_test.cairo +++ b/src/tests/operators/math/abs/abs_i32_test.cairo @@ -12,14 +12,16 @@ use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_neg_helper; #[test] #[available_gas(2000000000000000000)] fn tensor_abs() { - // 1D + // ===== 1D ===== // + let tensor = i32_tensor_1x3_neg_helper(); let result = tensor.abs(); assert((*result.data[0]).into() == 0, 'result[0] = 0'); assert((*result.data[1]).into() == 1, 'result[1] = 1'); assert((*result.data[2]).into() == 2, 'result[2] = 2'); - // 2D + // ===== 2D ===== // + let tensor = i32_tensor_2x2_neg_helper(); let result = tensor.abs(); assert((*result.data[0]).into() == 0, 'result[0] = 0'); @@ -27,7 +29,8 @@ fn tensor_abs() { assert((*result.data[2]).into() == 2, 'result[2] = 2'); assert((*result.data[3]).into() == 3, 'result[3] = 3'); - // 3D + // ===== 3D ===== // + let tensor = i32_tensor_2x2x2_neg_helper(); let result = tensor.abs(); assert((*result.data[0]).into() == 0, 'result[0] = 0'); diff --git a/src/tests/operators/math/abs/abs_u32_test.cairo b/src/tests/operators/math/abs/abs_u32_test.cairo index 94ac6ae3b..d01e0ffce 100644 --- a/src/tests/operators/math/abs/abs_u32_test.cairo +++ b/src/tests/operators/math/abs/abs_u32_test.cairo @@ -1,63 +1,50 @@ -#[cfg(test)] -mod tensor_1D { - use array::SpanTrait; - use array::ArrayTrait; - use orion::operators::tensor::implementations::impl_tensor_u32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; +use array::SpanTrait; +use array::ArrayTrait; +use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::tests::helpers::tensor::u32::{ + u32_tensor_1x3_helper, u32_tensor_2x2_helper, u32_tensor_2x2x2_helper +}; - #[test] - #[available_gas(20000000)] - fn abs_1D() { - let tensor = u32_tensor_1x3_helper(); - let result = tensor.abs(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - } +// ===== 1D ===== // + +#[test] +#[available_gas(20000000)] +fn tensor_abs_1D() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); } -#[cfg(test)] -mod tensor_2D { - use array::SpanTrait; - use array::ArrayTrait; - use orion::operators::tensor::implementations::impl_tensor_u32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; +// ===== 2D ===== // - #[test] - #[available_gas(20000000)] - fn abs_2D() { - let tensor = u32_tensor_2x2_helper(); - let result = tensor.abs(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - assert(*result.data[3] == 3, 'result[3] = 3'); - } +#[test] +#[available_gas(20000000)] +fn tensor_abs_2D() { + let tensor = u32_tensor_2x2_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); } -#[cfg(test)] -mod tensor_3D { - use array::SpanTrait; - use array::ArrayTrait; - use orion::operators::tensor::implementations::impl_tensor_u32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; +// ===== 3D ===== // - #[test] - #[available_gas(20000000)] - fn abs_3D() { - let tensor = u32_tensor_2x2x2_helper(); - let result = tensor.abs(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - assert(*result.data[3] == 3, 'result[3] = 3'); - assert(*result.data[4] == 4, 'result[4] = 4'); - assert(*result.data[5] == 5, 'result[5] = 5'); - assert(*result.data[6] == 6, 'result[6] = 6'); - assert(*result.data[7] == 7, 'result[7] = 7'); - } +#[test] +#[available_gas(20000000)] +fn tensor_abs_3D() { + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + assert(*result.data[4] == 4, 'result[4] = 4'); + assert(*result.data[5] == 5, 'result[5] = 5'); + assert(*result.data[6] == 6, 'result[6] = 6'); + assert(*result.data[7] == 7, 'result[7] = 7'); } diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo index 137d25c6e..5879d7226 100644 --- a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo +++ b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo @@ -1,109 +1,90 @@ -#[cfg(test)] -mod tensor_1D { - use array::SpanTrait; - use array::ArrayTrait; - use option::OptionTrait; - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; - use orion::numbers::fixed_point::implementations::impl_16x16; +use array::SpanTrait; +use array::ArrayTrait; +use option::OptionTrait; +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; +use orion::numbers::fixed_point::implementations::impl_16x16; - #[test] - #[available_gas(2000000)] - fn ceil_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(4); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(234, false)); // 0.00357627868 - arr.append(FixedTrait::new(786431, false)); // 11.9999947548 - arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); +// ===== 1D ===== // - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); - } +#[test] +#[available_gas(2000000)] +fn tensor_ceil_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } -#[cfg(test)] -mod tensor_2D { - use array::SpanTrait; - use array::ArrayTrait; - use option::OptionTrait; - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; - use orion::numbers::fixed_point::implementations::impl_16x16; +// ===== 2D ===== // - #[test] - #[available_gas(2000000)] - fn ceil_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(234, false)); // 0.00357627868 - arr.append(FixedTrait::new(786431, false)); // 11.9999947548 - arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); +#[test] +#[available_gas(2000000)] +fn tensor_ceil_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); - } + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } -#[cfg(test)] -mod tensor_3D { - use array::SpanTrait; - use array::ArrayTrait; - use option::OptionTrait; - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; - use orion::numbers::fixed_point::implementations::impl_16x16; +// ===== 3D ===== // - #[test] - #[available_gas(2000000)] - fn ceil_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); +#[test] +#[available_gas(2000000)] +fn tensor_ceil_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(234, false)); // 0.00357627868 - arr.append(FixedTrait::new(786431, false)); // 11.9999947548 - arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 - arr.append(FixedTrait::new(32768, false)); // 0.5 - arr.append(FixedTrait::new(32768, true)); // - 0.5 - arr.append(FixedTrait::new(98304, false)); // 1.5 - arr.append(FixedTrait::new(98304, true)); // - 1.5 + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + arr.append(FixedTrait::new(32768, false)); // 0.5 + arr.append(FixedTrait::new(32768, true)); // - 0.5 + arr.append(FixedTrait::new(98304, false)); // 1.5 + arr.append(FixedTrait::new(98304, true)); // - 1.5 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); - } + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo index 6beb19a06..a91c2894f 100644 --- a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo +++ b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo @@ -1,109 +1,90 @@ -#[cfg(test)] -mod tensor_1D { - use array::SpanTrait; - use array::ArrayTrait; - use option::OptionTrait; - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; - use orion::numbers::fixed_point::implementations::impl_8x23; +use array::SpanTrait; +use array::ArrayTrait; +use option::OptionTrait; +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; +use orion::numbers::fixed_point::implementations::impl_8x23; - #[test] - #[available_gas(2000000)] - fn ceil_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(4); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(30000, false)); // 0.00357627868 - arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 - arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); +// ===== 1D ===== // - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); - } +#[test] +#[available_gas(2000000)] +fn tensor_ceil_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } -#[cfg(test)] -mod tensor_2D { - use array::SpanTrait; - use array::ArrayTrait; - use option::OptionTrait; - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; - use orion::numbers::fixed_point::implementations::impl_8x23; +// ===== 2D ===== // - #[test] - #[available_gas(2000000)] - fn ceil_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(30000, false)); // 0.00357627868 - arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 - arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); +#[test] +#[available_gas(2000000)] +fn tensor_ceil_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); - } + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } -#[cfg(test)] -mod tensor_3D { - use array::SpanTrait; - use array::ArrayTrait; - use option::OptionTrait; - use orion::operators::tensor::implementations::impl_tensor_fp; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; - use orion::numbers::fixed_point::implementations::impl_8x23; +// ===== 3D ===== // - #[test] - #[available_gas(2000000)] - fn ceil_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); +#[test] +#[available_gas(2000000)] +fn tensor_ceil_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(30000, false)); // 0.00357627868 - arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 - arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 - arr.append(FixedTrait::new(4194304, false)); // 0.5 - arr.append(FixedTrait::new(4194304, true)); // - 0.5 - arr.append(FixedTrait::new(12582912, false)); // 1.5 - arr.append(FixedTrait::new(12582912, true)); // - 1.5 + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + arr.append(FixedTrait::new(4194304, false)); // 0.5 + arr.append(FixedTrait::new(4194304, true)); // - 0.5 + arr.append(FixedTrait::new(12582912, false)); // 1.5 + arr.append(FixedTrait::new(12582912, true)); // - 1.5 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); - } + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/math/ceil/ceil_i32_test.cairo b/src/tests/operators/math/ceil/ceil_i32_test.cairo index 40da59442..cb0ef3666 100644 --- a/src/tests/operators/math/ceil/ceil_i32_test.cairo +++ b/src/tests/operators/math/ceil/ceil_i32_test.cairo @@ -8,18 +8,19 @@ use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; - #[test] #[available_gas(2000000000000000000)] fn tensor_ceil() { - // 1D + // ===== 1D ===== // + let tensor = i32_tensor_1x3_helper(); let result = tensor.ceil(); assert((*result.data[0]).into() == 0, 'result[0] = 0'); assert((*result.data[1]).into() == 1, 'result[1] = 1'); assert((*result.data[2]).into() == 2, 'result[2] = 2'); - // 2D + // ===== 2D ===== // + let tensor = i32_tensor_2x2_helper(); let result = tensor.ceil(); assert((*result.data[0]).into() == 0, 'result[0] = 0'); @@ -27,7 +28,8 @@ fn tensor_ceil() { assert((*result.data[2]).into() == 2, 'result[2] = 2'); assert((*result.data[3]).into() == 3, 'result[3] = 3'); - // 3D + // ===== 3D ===== // + let tensor = i32_tensor_2x2x2_helper(); let result = tensor.ceil(); assert((*result.data[0]).into() == 0, 'result[0] = 0'); diff --git a/src/tests/operators/math/ceil/ceil_u32_test.cairo b/src/tests/operators/math/ceil/ceil_u32_test.cairo index 36d72c333..73b7f1d1b 100644 --- a/src/tests/operators/math/ceil/ceil_u32_test.cairo +++ b/src/tests/operators/math/ceil/ceil_u32_test.cairo @@ -1,63 +1,49 @@ -#[cfg(test)] -mod tensor_1D { - use array::SpanTrait; - use array::ArrayTrait; - use orion::operators::tensor::implementations::impl_tensor_u32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; +use array::SpanTrait; +use array::ArrayTrait; +use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::tests::helpers::tensor::u32::{ + u32_tensor_1x3_helper, u32_tensor_2x2_helper, u32_tensor_2x2x2_helper +}; - #[test] - #[available_gas(20000000)] - fn ceil_1D() { - let tensor = u32_tensor_1x3_helper(); - let result = tensor.ceil(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - } +// ===== 1D ===== // + +#[test] +#[available_gas(20000000)] +fn tensor_ceil_1D() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); } -#[cfg(test)] -mod tensor_2D { - use array::SpanTrait; - use array::ArrayTrait; - use orion::operators::tensor::implementations::impl_tensor_u32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; +// ===== 2D ===== // - #[test] - #[available_gas(20000000)] - fn ceil_2D() { - let tensor = u32_tensor_2x2_helper(); - let result = tensor.ceil(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - assert(*result.data[3] == 3, 'result[3] = 3'); - } +#[test] +#[available_gas(20000000)] +fn tensor_ceil_2D() { + let tensor = u32_tensor_2x2_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); } -#[cfg(test)] -mod tensor_3D { - use array::SpanTrait; - use array::ArrayTrait; - use orion::operators::tensor::implementations::impl_tensor_u32; - use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; +// ===== 3D ===== // - #[test] - #[available_gas(20000000)] - fn ceil_3D() { - let tensor = u32_tensor_2x2x2_helper(); - let result = tensor.ceil(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - assert(*result.data[3] == 3, 'result[3] = 3'); - assert(*result.data[4] == 4, 'result[4] = 4'); - assert(*result.data[5] == 5, 'result[5] = 5'); - assert(*result.data[6] == 6, 'result[6] = 6'); - assert(*result.data[7] == 7, 'result[7] = 7'); - } +#[test] +#[available_gas(20000000)] +fn tensor_ceil_3D() { + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + assert(*result.data[4] == 4, 'result[4] = 4'); + assert(*result.data[5] == 5, 'result[5] = 5'); + assert(*result.data[6] == 6, 'result[6] = 6'); + assert(*result.data[7] == 7, 'result[7] = 7'); } - From a52299f49d05ec2a2628fca9a1128dd0edbab2be Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 11:44:30 +0300 Subject: [PATCH 013/126] refactor tensor greater tests --- .../math/greater/greater_fp_test.cairo | 138 +-------- .../greater_fp16x16_test.cairo | 286 ++++++++++++++++++ .../greater_fp_test/greater_fp8x23_test.cairo | 286 ++++++++++++++++++ .../math/greater/greater_i32_test.cairo | 157 +++++++++- .../math/greater/greater_u32_test.cairo | 224 +++++++++++--- 5 files changed, 918 insertions(+), 173 deletions(-) create mode 100644 src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo create mode 100644 src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo diff --git a/src/tests/operators/math/greater/greater_fp_test.cairo b/src/tests/operators/math/greater/greater_fp_test.cairo index 031344b7e..f16be0649 100644 --- a/src/tests/operators/math/greater/greater_fp_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test.cairo @@ -1,135 +1,3 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; - -#[test] -#[available_gas(2000000)] -fn tensor_greater_fp() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(10, false)); - arr_2.append(FixedTrait::new(11, false)); - arr_2.append(FixedTrait::new(2, true)); - arr_2.append(FixedTrait::new(3, true)); - arr_2.append(FixedTrait::new(4, false)); - arr_2.append(FixedTrait::new(5, false)); - arr_2.append(FixedTrait::new(16, false)); - arr_2.append(FixedTrait::new(17, false)); - arr_2.append(FixedTrait::new(18, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_greater_fp_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - arr_1.append(FixedTrait::new(9, false)); - arr_1.append(FixedTrait::new(10, false)); - arr_1.append(FixedTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(0, false)); - arr_2.append(FixedTrait::new(1, false)); - arr_2.append(FixedTrait::new(2, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} +mod greater_fp8x23_test; +// TODO: The following panics with "Failed setting up runner." +// mod greater_fp16x16_test; diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo b/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo new file mode 100644 index 000000000..32139941e --- /dev/null +++ b/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo @@ -0,0 +1,286 @@ +use array::SpanTrait; +use array::{ArrayTrait}; + +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; +use orion::numbers::fixed_point::implementations::impl_16x16; + +// ===== 1D ===== // + +#[test] +#[available_gas(2000000000000)] +fn tensor_greater_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + +#[test] +#[available_gas(200000000000)] +fn tensor_greater_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(200000000000)] +fn tensor_greater_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000000000)] +fn tensor_greater_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000000000)] +fn tensor_greater_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo b/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo new file mode 100644 index 000000000..ee1b48916 --- /dev/null +++ b/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo @@ -0,0 +1,286 @@ +use array::SpanTrait; +use array::{ArrayTrait}; + +use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; +use orion::numbers::fixed_point::implementations::impl_8x23; + +// ===== 1D ===== // + +#[test] +#[available_gas(2000000000000)] +fn tensor_greater_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + +#[test] +#[available_gas(200000000000)] +fn tensor_greater_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(200000000000)] +fn tensor_greater_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000000000)] +fn tensor_greater_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000000000)] +fn tensor_greater_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} diff --git a/src/tests/operators/math/greater/greater_i32_test.cairo b/src/tests/operators/math/greater/greater_i32_test.cairo index 51eaa24fc..933c97eb6 100644 --- a/src/tests/operators/math/greater/greater_i32_test.cairo +++ b/src/tests/operators/math/greater/greater_i32_test.cairo @@ -5,10 +5,42 @@ use orion::operators::tensor::implementations::impl_tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +// ===== 1D ===== // #[test] -#[available_gas(2000000)] -fn tensor_greater_i32() { +#[available_gas(2000000000000)] +fn tensor_greater_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + +#[test] +#[available_gas(200000000000)] +fn tensor_greater_2D() { let mut sizes = ArrayTrait::new(); sizes.append(3); sizes.append(3); @@ -68,8 +100,8 @@ fn tensor_greater_i32() { } #[test] -#[available_gas(2000000)] -fn tensor_greater_i32_broadcast() { +#[available_gas(200000000000)] +fn tensor_greater_broadcast_2D() { let mut sizes_1 = ArrayTrait::new(); sizes_1.append(4); sizes_1.append(3); @@ -134,3 +166,120 @@ fn tensor_greater_i32_broadcast() { assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000000000)] +fn tensor_greater_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000000000)] +fn tensor_greater_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} diff --git a/src/tests/operators/math/greater/greater_u32_test.cairo b/src/tests/operators/math/greater/greater_u32_test.cairo index e8c6a9cbe..a79980a52 100644 --- a/src/tests/operators/math/greater/greater_u32_test.cairo +++ b/src/tests/operators/math/greater/greater_u32_test.cairo @@ -3,13 +3,185 @@ use array::{ArrayTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +// ===== 1D ===== // + #[test] #[available_gas(2000000)] -fn tensor_greater_u32() { +fn tensor_greater_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(1); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_greater_2D() { let mut sizes = ArrayTrait::new(); sizes.append(3); sizes.append(3); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000)] +fn tensor_greater_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_greater_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut arr_1 = ArrayTrait::::new(); arr_1.append(0_u32); arr_1.append(1_u32); @@ -19,7 +191,6 @@ fn tensor_greater_u32() { arr_1.append(7_u32); arr_1.append(6_u32); arr_1.append(7_u32); - arr_1.append(8_u32); let mut arr_2 = ArrayTrait::::new(); arr_2.append(10_u32); @@ -30,7 +201,6 @@ fn tensor_greater_u32() { arr_2.append(5_u32); arr_2.append(16_u32); arr_2.append(17_u32); - arr_2.append(18_u32); let extra = Option::::None(()); @@ -46,7 +216,6 @@ fn tensor_greater_u32() { assert(*result_a.data.at(5) == 1, 'result[5] = 1'); assert(*result_a.data.at(6) == 0, 'result[6] = 0'); assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); @@ -59,40 +228,36 @@ fn tensor_greater_u32() { assert(*result_b.data.at(5) == 0, 'result[5] = 0'); assert(*result_b.data.at(6) == 1, 'result[6] = 1'); assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } #[test] #[available_gas(2000000)] -fn tensor_greater_u32_broadcast() { +fn tensor_greater_broadcast_3D() { let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); let mut sizes_2 = ArrayTrait::new(); sizes_2.append(1); - sizes_2.append(3); + sizes_2.append(2); + sizes_2.append(1); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); - arr_1.append(9_u32); - arr_1.append(10_u32); - arr_1.append(11_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0_u32); - arr_2.append(1_u32); - arr_2.append(2_u32); + arr_2.append(0); + arr_2.append(1); let extra = Option::::None(()); @@ -108,26 +273,17 @@ fn tensor_greater_u32_broadcast() { assert(*result_a.data.at(5) == 0, 'result[5] = 0'); assert(*result_a.data.at(6) == 0, 'result[6] = 0'); assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); assert(*result_b.data.at(0) == 0, 'result[0] = 0'); assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); assert(*result_b.data.at(3) == 1, 'result[3] = 1'); assert(*result_b.data.at(4) == 1, 'result[4] = 1'); assert(*result_b.data.at(5) == 1, 'result[5] = 1'); assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } From 4a8fcb061bb2c63ec50677adcc5c3e82b980ad39 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 12:18:58 +0300 Subject: [PATCH 014/126] refactor greater_equal_u32 tests --- .../greater_equal_u32_test.cairo | 224 +++++++++++++++--- 1 file changed, 190 insertions(+), 34 deletions(-) diff --git a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo index b189a197f..468c9ebdc 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo @@ -3,13 +3,185 @@ use array::{ArrayTrait}; use orion::operators::tensor::implementations::impl_tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +// ===== 1D ===== // + #[test] #[available_gas(2000000)] -fn tensor_greater_equal_u32() { +fn tensor_greater_equal_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 2D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_greater_equal_2D() { let mut sizes = ArrayTrait::new(); sizes.append(3); sizes.append(3); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 1, 'result[4] = 0'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +#[test] +#[available_gas(2000000)] +fn tensor_greater_equal_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +} + +// ===== 3D ===== // + +#[test] +#[available_gas(2000000)] +fn tensor_greater_equal_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut arr_1 = ArrayTrait::::new(); arr_1.append(0_u32); arr_1.append(1_u32); @@ -19,7 +191,6 @@ fn tensor_greater_equal_u32() { arr_1.append(7_u32); arr_1.append(6_u32); arr_1.append(7_u32); - arr_1.append(8_u32); let mut arr_2 = ArrayTrait::::new(); arr_2.append(10_u32); @@ -30,7 +201,6 @@ fn tensor_greater_equal_u32() { arr_2.append(5_u32); arr_2.append(16_u32); arr_2.append(17_u32); - arr_2.append(18_u32); let extra = Option::::None(()); @@ -46,7 +216,6 @@ fn tensor_greater_equal_u32() { assert(*result_a.data.at(5) == 1, 'result[5] = 1'); assert(*result_a.data.at(6) == 0, 'result[6] = 0'); assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); @@ -59,40 +228,36 @@ fn tensor_greater_equal_u32() { assert(*result_b.data.at(5) == 0, 'result[5] = 0'); assert(*result_b.data.at(6) == 1, 'result[6] = 1'); assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } #[test] #[available_gas(2000000)] -fn tensor_greater_equal_u32_broadcast() { +fn tensor_greater_equal_broadcast_3D() { let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); let mut sizes_2 = ArrayTrait::new(); sizes_2.append(1); - sizes_2.append(3); + sizes_2.append(2); + sizes_2.append(1); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); - arr_1.append(9_u32); - arr_1.append(10_u32); - arr_1.append(11_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0_u32); - arr_2.append(1_u32); - arr_2.append(2_u32); + arr_2.append(0); + arr_2.append(1); let extra = Option::::None(()); @@ -102,16 +267,12 @@ fn tensor_greater_equal_u32_broadcast() { let result_a = tensor_b.greater_equal(@tensor_a); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); assert(*result_a.data.at(3) == 0, 'result[3] = 0'); assert(*result_a.data.at(4) == 0, 'result[4] = 0'); assert(*result_a.data.at(5) == 0, 'result[5] = 0'); assert(*result_a.data.at(6) == 0, 'result[6] = 0'); assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); @@ -123,11 +284,6 @@ fn tensor_greater_equal_u32_broadcast() { assert(*result_b.data.at(4) == 1, 'result[4] = 1'); assert(*result_b.data.at(5) == 1, 'result[5] = 1'); assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } From ea24936e838fcbe83c9acf4cca4111780ceb2af0 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 13:07:01 +0300 Subject: [PATCH 015/126] Update greater_fp_test.cairo --- src/tests/operators/math/greater/greater_fp_test.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/operators/math/greater/greater_fp_test.cairo b/src/tests/operators/math/greater/greater_fp_test.cairo index f16be0649..8920240a6 100644 --- a/src/tests/operators/math/greater/greater_fp_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test.cairo @@ -1,3 +1,3 @@ mod greater_fp8x23_test; -// TODO: The following panics with "Failed setting up runner." +// TODO: The following panics with "Failed setting up runner. - Failed calculating gas usage" // mod greater_fp16x16_test; From 96ed910373f37f8d6cbf1194d37f6e2b695c619d Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 19:07:57 +0300 Subject: [PATCH 016/126] fix build errors --- .../operators/neural-network/nn.leaky_relu.md | 2 +- .../operators/neural-network/nn.linear.md | 2 +- .../operators/neural-network/nn.logsoftmax.md | 2 +- docs/apis/operators/neural-network/nn.relu.md | 2 +- .../operators/neural-network/nn.sigmoid.md | 2 +- .../operators/neural-network/nn.softmax.md | 2 +- .../operators/neural-network/nn.softplus.md | 2 +- .../operators/neural-network/nn.softsign.md | 2 +- ...ication-with-feedforward-neural-network.md | 8 +- .../mnist-classification-with-orion.md | 8 +- .../implementations/impl_16x16.cairo | 34 ++++----- .../implementations/impl_8x23.cairo | 8 +- src/numbers/fixed_point/math/math_16x16.cairo | 9 ++- src/numbers/fixed_point/math/math_8x23.cairo | 9 ++- src/numbers/signed_integer/i128.cairo | 14 ++-- src/numbers/signed_integer/i16.cairo | 14 ++-- src/numbers/signed_integer/i32.cairo | 14 ++-- src/numbers/signed_integer/i64.cairo | 14 ++-- src/numbers/signed_integer/i8.cairo | 14 ++-- src/operators/nn/core.cairo | 16 ++-- .../leaky_relu/leaky_relu_i32/fp16x16.cairo | 10 +-- .../leaky_relu/leaky_relu_i32/fp8x23.cairo | 10 +-- .../leaky_relu/leaky_relu_u32/fp16x16.cairo | 6 +- .../leaky_relu/leaky_relu_u32/fp8x23.cairo | 6 +- .../nn/functional/linear/linear_i32.cairo | 4 +- .../nn/functional/linear/linear_u32.cairo | 4 +- .../logsoftmax/logsoftmax_i32.cairo | 7 +- .../logsoftmax/logsoftmax_u32.cairo | 7 +- .../nn/functional/relu/relu_i32.cairo | 2 +- .../nn/functional/relu/relu_u32.cairo | 2 +- .../sigmoid/sigmoid_i32/fp16x16.cairo | 5 +- .../sigmoid/sigmoid_i32/fp8x23.cairo | 4 +- .../sigmoid/sigmoid_u32/fp16x16.cairo | 4 +- .../sigmoid/sigmoid_u32/fp8x23.cairo | 4 +- .../nn/functional/softmax/softmax_i32.cairo | 5 +- .../nn/functional/softmax/softmax_u32.cairo | 5 +- .../softplus/softplus_i32/fp16x16.cairo | 4 +- .../softplus/softplus_i32/fp8x23.cairo | 4 +- .../softplus/softplus_u32/fp16x16.cairo | 4 +- .../softplus/softplus_u32/fp8x23.cairo | 4 +- .../softsign/softsign_i32/fp16x16.cairo | 4 +- .../softsign/softsign_i32/fp8x23.cairo | 4 +- .../softsign/softsign_u32/fp16x16.cairo | 4 +- .../softsign/softsign_u32/fp8x23.cairo | 4 +- src/operators/tensor/helpers.cairo | 4 +- .../implementations/impl_tensor_u32.cairo | 8 +- .../tensor/linalg/matmul/helpers.cairo | 4 +- .../linalg/matmul/matmul_fp/fp16x16.cairo | 11 +-- .../linalg/matmul/matmul_fp/fp8x23.cairo | 9 +-- .../tensor/linalg/matmul/matmul_i32.cairo | 6 +- .../tensor/linalg/matmul/matmul_u32.cairo | 6 +- .../linalg/transpose/transpose_fp/core.cairo | 2 +- .../transpose/transpose_fp/fp16x16.cairo | 4 +- .../transpose/transpose_fp/fp8x23.cairo | 4 +- .../linalg/transpose/transpose_i32.cairo | 2 +- .../linalg/transpose/transpose_u32.cairo | 2 +- .../tensor/math/abs/abs_fp/core.cairo | 2 +- .../tensor/math/abs/abs_fp/fp16x16.cairo | 5 +- .../tensor/math/abs/abs_fp/fp8x23.cairo | 5 +- src/operators/tensor/math/abs/abs_i32.cairo | 2 +- .../math/argmax/argmax_fp/fp16x16.cairo | 31 ++++---- .../tensor/math/argmax/argmax_fp/fp8x23.cairo | 31 ++++---- .../tensor/math/argmax/argmax_i32.cairo | 25 +++--- .../tensor/math/argmax/argmax_u32.cairo | 22 +++--- .../tensor/math/argmax/helpers.cairo | 76 ++++++++++--------- .../math/argmin/argmin_fp/fp16x16.cairo | 9 ++- .../tensor/math/argmin/argmin_fp/fp8x23.cairo | 9 ++- .../tensor/math/argmin/argmin_i32.cairo | 2 +- .../tensor/math/argmin/argmin_u32.cairo | 2 +- .../tensor/math/argmin/helpers.cairo | 2 +- .../arithmetic/arithmetic_fp/fp16x16.cairo | 8 +- .../arithmetic/arithmetic_fp/fp8x23.cairo | 10 +-- .../math/arithmetic/arithmetic_i32.cairo | 2 +- .../math/arithmetic/arithmetic_u32.cairo | 2 +- .../tensor/math/ceil/ceil_fp/core.cairo | 2 +- .../tensor/math/ceil/ceil_fp/fp16x16.cairo | 4 +- .../tensor/math/ceil/ceil_fp/fp8x23.cairo | 4 +- .../tensor/math/equal/equal_fp/fp16x16.cairo | 6 +- .../tensor/math/equal/equal_fp/fp8x23.cairo | 6 +- .../tensor/math/equal/equal_i32.cairo | 2 +- .../tensor/math/equal/equal_u32.cairo | 2 +- .../tensor/math/exp/exp_fp/fp16x16.cairo | 5 +- .../tensor/math/exp/exp_fp/fp8x23.cairo | 5 +- .../tensor/math/exp/exp_i32/fp16x16.cairo | 5 +- .../tensor/math/exp/exp_i32/fp8x23.cairo | 5 +- .../tensor/math/exp/exp_u32/fp16x16.cairo | 5 +- .../tensor/math/exp/exp_u32/fp8x23.cairo | 5 +- .../math/greater/greater_fp/fp16x16.cairo | 23 +++--- .../math/greater/greater_fp/fp8x23.cairo | 4 +- .../tensor/math/greater/greater_i32.cairo | 2 +- .../tensor/math/greater/greater_u32.cairo | 2 +- .../greater_equal_fp/fp16x16.cairo | 4 +- .../greater_equal_fp/fp8x23.cairo | 4 +- .../greater_equal/greater_equal_i32.cairo | 2 +- .../greater_equal/greater_equal_u32.cairo | 2 +- .../tensor/math/less/less_fp/fp16x16.cairo | 4 +- .../tensor/math/less/less_fp/fp8x23.cairo | 4 +- src/operators/tensor/math/less/less_i32.cairo | 2 +- src/operators/tensor/math/less/less_u32.cairo | 2 +- .../less_equal/less_equal_fp/fp16x16.cairo | 5 +- .../less_equal/less_equal_fp/fp8x23.cairo | 5 +- .../math/less_equal/less_equal_i32.cairo | 2 +- .../math/less_equal/less_equal_u32.cairo | 2 +- .../tensor/math/ln/ln_fp/fp16x16.cairo | 5 +- .../tensor/math/ln/ln_fp/fp8x23.cairo | 5 +- .../tensor/math/ln/ln_i32/fp16x16.cairo | 5 +- .../tensor/math/ln/ln_i32/fp8x23.cairo | 5 +- .../tensor/math/ln/ln_u32/fp16x16.cairo | 4 +- .../tensor/math/ln/ln_u32/fp8x23.cairo | 5 +- .../tensor/math/max/max_fp/fp16x16.cairo | 4 +- .../tensor/math/max/max_fp/fp8x23.cairo | 5 +- .../tensor/math/min/min_fp/fp16x16.cairo | 5 +- .../tensor/math/min/min_fp/fp8x23.cairo | 5 +- src/operators/tensor/math/min/min_u32.cairo | 2 +- .../reduce_sum/reduce_sum_fp/fp16x16.cairo | 8 +- .../reduce_sum/reduce_sum_fp/fp8x23.cairo | 8 +- .../math/reduce_sum/reduce_sum_i32.cairo | 2 +- .../math/reduce_sum/reduce_sum_u32.cairo | 2 +- .../quantization/quant_fp/fp16x16.cairo | 7 +- .../quantization/quant_fp/fp8x23.cairo | 7 +- .../functional/quantization/quant_i32.cairo | 4 +- .../functional/quantization/quant_u32.cairo | 4 +- .../impl_performance_i32.cairo | 2 +- .../impl_performance_u32.cairo | 2 +- .../numbers/fixed_point/fp16x16_test.cairo | 7 +- .../numbers/fixed_point/fp8x23_test.cairo | 7 +- src/tests/numbers/signed_integer_test.cairo | 10 +-- src/tests/operators/linalg/matmul_test.cairo | 2 +- .../operators/math/abs/abs_fp_test.cairo | 8 +- .../operators/math/abs/abs_i32_test.cairo | 2 +- .../operators/math/abs/abs_u32_test.cairo | 2 +- .../argmax_fp_test/argmax_fp16x16_test.cairo | 12 +-- .../argmax_fp_test/argmax_fp8x23_test.cairo | 12 +-- .../math/argmax/argmax_i32_test.cairo | 6 +- .../math/argmax/argmax_u32_test.cairo | 6 +- .../argmin_fp_test/argmin_fp16x16_test.cairo | 12 +-- .../argmin_fp_test/argmin_fp8x23_test.cairo | 12 +-- .../math/argmin/argmin_i32_test.cairo | 6 +- .../math/argmin/argmin_u32_test.cairo | 6 +- .../operators/math/ceil/ceil_fp_test.cairo | 16 ++-- .../operators/math/ceil/ceil_i32_test.cairo | 2 +- .../operators/math/ceil/ceil_u32_test.cairo | 2 +- .../operators/math/equal/equal_fp_test.cairo | 4 +- .../operators/math/equal/equal_i32_test.cairo | 2 +- .../operators/math/equal/equal_u32_test.cairo | 2 +- src/tests/operators/math/exp_test.cairo | 4 +- .../math/greater/greater_fp_test.cairo | 4 +- .../math/greater/greater_i32_test.cairo | 2 +- .../math/greater/greater_u32_test.cairo | 2 +- .../greater_equal/greater_equal_fp_test.cairo | 5 +- .../greater_equal_i32_test.cairo | 2 +- .../greater_equal_u32_test.cairo | 2 +- .../operators/math/less/less_fp_test.cairo | 5 +- .../operators/math/less/less_i32_test.cairo | 2 +- .../operators/math/less/less_u32_test.cairo | 2 +- .../math/less_equal/less_equal_fp_test.cairo | 5 +- .../math/less_equal/less_equal_i32_test.cairo | 2 +- .../math/less_equal/less_equal_u32_test.cairo | 2 +- src/tests/operators/math/ln_test.cairo | 4 +- src/tests/operators/math/max_test.cairo | 2 +- src/tests/operators/math/min_test.cairo | 2 +- .../operators/math/reduce_sum_test.cairo | 2 +- .../leaky_relu/leaky_relu_i32_test.cairo | 8 +- .../leaky_relu/leaky_relu_u32_test.cairo | 6 +- .../nn/functional/linear/linear_test.cairo | 17 +++-- .../logsoftmax/logsoftmax_test.cairo | 4 +- .../nn/functional/relu/relu_i32_test.cairo | 4 +- .../nn/functional/relu/relu_u32_test.cairo | 4 +- .../functional/sigmoid/sigmoid_i32_test.cairo | 4 +- .../functional/sigmoid/sigmoid_u32_test.cairo | 4 +- .../nn/functional/softmax/softmax_test.cairo | 4 +- .../softplus/softplus_i32_test.cairo | 4 +- .../softplus/softplus_u32_test.cairo | 6 +- .../softsign/softsign_i32_test.cairo | 4 +- .../softsign/softsign_u32_test.cairo | 6 +- .../helpers/helpers_fp/fp16x16_helpers.cairo | 4 +- .../helpers/helpers_fp/fp8x23_helpers.cairo | 5 +- .../tensor/helpers/helpers_i32.cairo | 2 +- .../tensor/helpers/helpers_u32.cairo | 2 +- src/tests/operators/tensor/tensor_test.cairo | 4 +- src/tests/performance/quantization_test.cairo | 8 +- src/utils.cairo | 6 +- 182 files changed, 549 insertions(+), 567 deletions(-) diff --git a/docs/apis/operators/neural-network/nn.leaky_relu.md b/docs/apis/operators/neural-network/nn.leaky_relu.md index 57f2de35d..939479bec 100644 --- a/docs/apis/operators/neural-network/nn.leaky_relu.md +++ b/docs/apis/operators/neural-network/nn.leaky_relu.md @@ -24,7 +24,7 @@ A new FixedType tensor with the same shape as the input tensor and the Leaky ReL ```rust use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; fn leaky_relu_example() -> Tensor { // We instantiate a 2D Tensor here, the alpha and set threshold to 0. diff --git a/docs/apis/operators/neural-network/nn.linear.md b/docs/apis/operators/neural-network/nn.linear.md index 8066997ed..dadeee8bb 100644 --- a/docs/apis/operators/neural-network/nn.linear.md +++ b/docs/apis/operators/neural-network/nn.linear.md @@ -25,7 +25,7 @@ A `Tensor` representing the result of the linear transformation, possibly qua ```rust use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; fn linear_layer_example() -> Tensor { // We instantiate inputs here. diff --git a/docs/apis/operators/neural-network/nn.logsoftmax.md b/docs/apis/operators/neural-network/nn.logsoftmax.md index 5db2cfc2a..7aeaab3bf 100644 --- a/docs/apis/operators/neural-network/nn.logsoftmax.md +++ b/docs/apis/operators/neural-network/nn.logsoftmax.md @@ -23,7 +23,7 @@ A Tensor of fixed point numbers with the same shape than the input Tensor. ```rust use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; fn logsoftmax_example() -> Tensor { // We instantiate a 2D Tensor here. diff --git a/docs/apis/operators/neural-network/nn.relu.md b/docs/apis/operators/neural-network/nn.relu.md index 0b22b6113..c3cd7397d 100644 --- a/docs/apis/operators/neural-network/nn.relu.md +++ b/docs/apis/operators/neural-network/nn.relu.md @@ -23,7 +23,7 @@ A `Tensor` with the same shape as the input tensor. ```rust use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; fn relu_example() -> Tensor { // We instantiate a 2D Tensor here and set threshold to 0. diff --git a/docs/apis/operators/neural-network/nn.sigmoid.md b/docs/apis/operators/neural-network/nn.sigmoid.md index 0afef652d..0a71c439c 100644 --- a/docs/apis/operators/neural-network/nn.sigmoid.md +++ b/docs/apis/operators/neural-network/nn.sigmoid.md @@ -22,7 +22,7 @@ A Tensor of fixed point numbers with the same shape than the input Tensor. ```rust use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; fn sigmoid_example() -> Tensor { // We instantiate a 2D Tensor here. diff --git a/docs/apis/operators/neural-network/nn.softmax.md b/docs/apis/operators/neural-network/nn.softmax.md index a60e2a197..ccee20b41 100644 --- a/docs/apis/operators/neural-network/nn.softmax.md +++ b/docs/apis/operators/neural-network/nn.softmax.md @@ -23,7 +23,7 @@ A Tensor of fixed point numbers with the same shape than the input Tensor. ```rust use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; fn softmax_example() -> Tensor { // We instantiate a 2D Tensor here. diff --git a/docs/apis/operators/neural-network/nn.softplus.md b/docs/apis/operators/neural-network/nn.softplus.md index c5da0d5f0..ba85c69b7 100644 --- a/docs/apis/operators/neural-network/nn.softplus.md +++ b/docs/apis/operators/neural-network/nn.softplus.md @@ -22,7 +22,7 @@ A Tensor of fixed point numbers with the same shape than the input Tensor. ```rust use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; fn softplus_example() -> Tensor { // We instantiate a 2D Tensor here. diff --git a/docs/apis/operators/neural-network/nn.softsign.md b/docs/apis/operators/neural-network/nn.softsign.md index 65d289b64..95f164f10 100644 --- a/docs/apis/operators/neural-network/nn.softsign.md +++ b/docs/apis/operators/neural-network/nn.softsign.md @@ -22,7 +22,7 @@ A Tensor of fixed point numbers with the same shape than the input Tensor. ```rust use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; fn softsign_example() -> Tensor { // We instantiate a 2D Tensor here. diff --git a/docs/resources/tutorials/mnist-classification-with-feedforward-neural-network.md b/docs/resources/tutorials/mnist-classification-with-feedforward-neural-network.md index 069020f21..73de7e898 100644 --- a/docs/resources/tutorials/mnist-classification-with-feedforward-neural-network.md +++ b/docs/resources/tutorials/mnist-classification-with-feedforward-neural-network.md @@ -392,7 +392,7 @@ for tensor_name, tensor in tensors.items(): f.write( "use array::ArrayTrait;\n" + "use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams};\n" + - "use orion::operators::tensor::implementations::impl_tensor_i32;\n" + + "use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32;\n" + "use orion::numbers::fixed_point::core::FixedImpl;\n" + "use orion::numbers::signed_integer::i32::i32;\n\n" + "fn {0}() -> Tensor<i32> ".format(tensor_name) + "{\n" + @@ -434,7 +434,7 @@ Here is a file we generated: `fc1_bias.cairo` ```rust use array::ArrayTrait; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; use orion::numbers::signed_integer::i32::i32; @@ -540,7 +540,7 @@ use orion::operators::tensor::core::Tensor; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; fn fc1(i: Tensor, w: Tensor, b: Tensor) -> Tensor { let x = NNTrait::linear(i, w, b, true); // `true` because we want to quantize the result @@ -557,7 +557,7 @@ use orion::operators::tensor::core::Tensor; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; fn fc1(i: Tensor, w: Tensor, b: Tensor) -> Tensor { let x = NNTrait::linear(i, w, b, true); diff --git a/docs/resources/tutorials/mnist-classification-with-orion.md b/docs/resources/tutorials/mnist-classification-with-orion.md index 0ad7930d4..fe4096a32 100644 --- a/docs/resources/tutorials/mnist-classification-with-orion.md +++ b/docs/resources/tutorials/mnist-classification-with-orion.md @@ -393,7 +393,7 @@ for tensor_name, tensor in tensors.items(): f.write( "use array::ArrayTrait;\n" + "use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams};\n" + - "use orion::operators::tensor::implementations::impl_tensor_i32;\n" + + "use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32;\n" + "use orion::numbers::fixed_point::core::FixedImpl;\n" + "use orion::numbers::signed_integer::i32::i32;\n\n" + "fn {0}() -> Tensor<i32> ".format(tensor_name) + "{\n" + @@ -435,7 +435,7 @@ Here is a file we generated: `fc1_bias.cairo` ```rust use array::ArrayTrait; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; use orion::numbers::signed_integer::i32::i32; @@ -541,7 +541,7 @@ use orion::operators::tensor::core::Tensor; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; fn fc1(i: Tensor, w: Tensor, b: Tensor) -> Tensor { let x = NNTrait::linear(i, w, b, true); // `true` because we want to quantize the result @@ -558,7 +558,7 @@ use orion::operators::tensor::core::Tensor; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; fn fc1(i: Tensor, w: Tensor, b: Tensor) -> Tensor { let x = NNTrait::linear(i, w, b, true); diff --git a/src/numbers/fixed_point/implementations/impl_16x16.cairo b/src/numbers/fixed_point/implementations/impl_16x16.cairo index beb0f3e15..943df4761 100644 --- a/src/numbers/fixed_point/implementations/impl_16x16.cairo +++ b/src/numbers/fixed_point/implementations/impl_16x16.cairo @@ -83,14 +83,14 @@ impl FP16x16Impl of FixedTrait { } } -impl fp16x16Print of PrintTrait { +impl FP16x16Print of PrintTrait { fn print(self: FixedType) { self.sign.print(); self.mag.print(); } } -impl fp16x16Into of Into { +impl FP16x16Into of Into { fn into(self: FixedType) -> felt252 { let mag_felt = self.mag.into(); @@ -102,71 +102,71 @@ impl fp16x16Into of Into { } } -impl fp16x16PartialEq of PartialEq { +impl FP16x16PartialEq of PartialEq { #[inline(always)] - fn eq(lhs: FixedType, rhs: FixedType) -> bool { - return math_16x16::eq(lhs, rhs); + fn eq(lhs: @FixedType, rhs: @FixedType) -> bool { + return math_16x16::eq(*lhs, *rhs); } #[inline(always)] - fn ne(lhs: FixedType, rhs: FixedType) -> bool { - return math_16x16::ne(lhs, rhs); + fn ne(lhs: @FixedType, rhs: @FixedType) -> bool { + return math_16x16::ne(*lhs, *rhs); } } -impl fp16x16Add of Add { +impl FP16x16Add of Add { fn add(lhs: FixedType, rhs: FixedType) -> FixedType { return math_16x16::add(lhs, rhs); } } -impl fp16x16AddEq of AddEq { +impl FP16x16AddEq of AddEq { #[inline(always)] fn add_eq(ref self: FixedType, other: FixedType) { self = Add::add(self, other); } } -impl fp16x16Sub of Sub { +impl FP16x16Sub of Sub { fn sub(lhs: FixedType, rhs: FixedType) -> FixedType { return math_16x16::sub(lhs, rhs); } } -impl fp16x16SubEq of SubEq { +impl FP16x16SubEq of SubEq { #[inline(always)] fn sub_eq(ref self: FixedType, other: FixedType) { self = Sub::sub(self, other); } } -impl fp16x16Mul of Mul { +impl FP16x16Mul of Mul { fn mul(lhs: FixedType, rhs: FixedType) -> FixedType { return math_16x16::mul(lhs, rhs); } } -impl fp16x16MulEq of MulEq { +impl FP16x16MulEq of MulEq { #[inline(always)] fn mul_eq(ref self: FixedType, other: FixedType) { self = Mul::mul(self, other); } } -impl fp16x16Div of Div { +impl FP16x16Div of Div { fn div(lhs: FixedType, rhs: FixedType) -> FixedType { return math_16x16::div(lhs, rhs); } } -impl fp16x16DivEq of DivEq { +impl FP16x16DivEq of DivEq { #[inline(always)] fn div_eq(ref self: FixedType, other: FixedType) { self = Div::div(self, other); } } -impl fp16x16PartialOrd of PartialOrd { +impl FP16x16PartialOrd of PartialOrd { #[inline(always)] fn ge(lhs: FixedType, rhs: FixedType) -> bool { return math_16x16::ge(lhs, rhs); @@ -188,7 +188,7 @@ impl fp16x16PartialOrd of PartialOrd { } } -impl fp16x16Neg of Neg { +impl FP16x16Neg of Neg { #[inline(always)] fn neg(a: FixedType) -> FixedType { return math_16x16::neg(a); diff --git a/src/numbers/fixed_point/implementations/impl_8x23.cairo b/src/numbers/fixed_point/implementations/impl_8x23.cairo index fa2eaa577..97428ddf3 100644 --- a/src/numbers/fixed_point/implementations/impl_8x23.cairo +++ b/src/numbers/fixed_point/implementations/impl_8x23.cairo @@ -104,13 +104,13 @@ impl FP8x23Into of Into { impl FP8x23PartialEq of PartialEq { #[inline(always)] - fn eq(lhs: FixedType, rhs: FixedType) -> bool { - return math_8x23::eq(lhs, rhs); + fn eq(lhs: @FixedType, rhs: @FixedType) -> bool { + return math_8x23::eq(*lhs, *rhs); } #[inline(always)] - fn ne(lhs: FixedType, rhs: FixedType) -> bool { - return math_8x23::ne(lhs, rhs); + fn ne(lhs: @FixedType, rhs: @FixedType) -> bool { + return math_8x23::ne(*lhs, *rhs); } } diff --git a/src/numbers/fixed_point/math/math_16x16.cairo b/src/numbers/fixed_point/math/math_16x16.cairo index c125c7f61..02c451481 100644 --- a/src/numbers/fixed_point/math/math_16x16.cairo +++ b/src/numbers/fixed_point/math/math_16x16.cairo @@ -1,7 +1,10 @@ use traits::Into; use orion::numbers::fixed_point::implementations::impl_16x16::{ONE, ONE_u64, MAX, HALF}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Add, FP16x16AddEq, FP16x16Into, FP16x16Print, FP16x16PartialEq, FP16x16Sub, + FP16x16SubEq, FP16x16Mul, FP16x16MulEq, FP16x16Div, FP16x16DivEq, FP16x16PartialOrd, FP16x16Neg +}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::utils::check_gas; @@ -71,7 +74,7 @@ fn div(a: FixedType, b: FixedType) -> FixedType { /// /// * A boolean value that indicates whether the input fixed point numbers are equal. fn eq(a: FixedType, b: FixedType) -> bool { - return a.mag == b.mag & a.sign == b.sign; + return (a.mag == b.mag) & (a.sign == b.sign); } /// Cf: FixedTrait::exp docstring @@ -283,7 +286,7 @@ fn mul(a: FixedType, b: FixedType) -> FixedType { /// /// * A boolean value that indicates whether the first fixed point number is not equal to the second fixed point number. fn ne(a: FixedType, b: FixedType) -> bool { - return a.mag != b.mag | a.sign != b.sign; + return (a.mag != b.mag) | (a.sign != b.sign); } /// Negates a fixed point number. diff --git a/src/numbers/fixed_point/math/math_8x23.cairo b/src/numbers/fixed_point/math/math_8x23.cairo index d4c3effa8..08e8c4b64 100644 --- a/src/numbers/fixed_point/math/math_8x23.cairo +++ b/src/numbers/fixed_point/math/math_8x23.cairo @@ -1,7 +1,10 @@ use traits::Into; use orion::numbers::fixed_point::implementations::impl_8x23::{ONE, ONE_u64, MAX, HALF}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Impl, FP8x23Add, FP8x23AddEq, FP8x23Into, FP8x23Print, FP8x23PartialEq, FP8x23Sub, + FP8x23SubEq, FP8x23Mul, FP8x23MulEq, FP8x23Div, FP8x23DivEq, FP8x23PartialOrd, FP8x23Neg +}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::utils::check_gas; @@ -71,7 +74,7 @@ fn div(a: FixedType, b: FixedType) -> FixedType { /// /// * A boolean value that indicates whether the input fixed point numbers are equal. fn eq(a: FixedType, b: FixedType) -> bool { - return a.mag == b.mag & a.sign == b.sign; + return (a.mag == b.mag) & (a.sign == b.sign); } /// Cf: FixedTrait::exp docstring @@ -285,7 +288,7 @@ fn mul(a: FixedType, b: FixedType) -> FixedType { /// /// * A boolean value that indicates whether the first fixed point number is not equal to the second fixed point number. fn ne(a: FixedType, b: FixedType) -> bool { - return a.mag != b.mag | a.sign != b.sign; + return (a.mag != b.mag) | (a.sign != b.sign); } /// Negates a fixed point number. diff --git a/src/numbers/signed_integer/i128.cairo b/src/numbers/signed_integer/i128.cairo index 48ebe1871..3319b6635 100644 --- a/src/numbers/signed_integer/i128.cairo +++ b/src/numbers/signed_integer/i128.cairo @@ -126,12 +126,12 @@ impl i128RemEq of RemEq { // Implements the PartialEq trait for i128. impl i128PartialEq of PartialEq { - fn eq(lhs: i128, rhs: i128) -> bool { - i128_eq(lhs, rhs) + fn eq(lhs: @i128, rhs: @i128) -> bool { + i128_eq(*lhs, *rhs) } - fn ne(lhs: i128, rhs: i128) -> bool { - i128_ne(lhs, rhs) + fn ne(lhs: @i128, rhs: @i128) -> bool { + i128_ne(*lhs, *rhs) } } @@ -337,7 +337,7 @@ fn i128_div_rem(a: i128, b: i128) -> (i128, i128) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i128_eq(a: i128, b: i128) -> bool { // Check if the two integers have the same sign and the same absolute value. - if a.sign == b.sign & a.mag == b.mag { + if (a.sign == b.sign) & (a.mag == b.mag) { return true; } @@ -399,7 +399,7 @@ fn i128_lt(a: i128, b: i128) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i128_le(a: i128, b: i128) -> bool { - if (a == b | i128_lt(a, b) == true) { + if ((a == b) | (i128_lt(a, b) == true)) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i128_le(a: i128, b: i128) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i128_ge(a: i128, b: i128) -> bool { - if (a == b | i128_gt(a, b) == true) { + if ((a == b) | (i128_gt(a, b) == true)) { return true; } else { return false; diff --git a/src/numbers/signed_integer/i16.cairo b/src/numbers/signed_integer/i16.cairo index 66631ff23..86d8157ad 100644 --- a/src/numbers/signed_integer/i16.cairo +++ b/src/numbers/signed_integer/i16.cairo @@ -126,12 +126,12 @@ impl i16RemEq of RemEq { // Implements the PartialEq trait for i16. impl i16PartialEq of PartialEq { - fn eq(lhs: i16, rhs: i16) -> bool { - i16_eq(lhs, rhs) + fn eq(lhs: @i16, rhs: @i16) -> bool { + i16_eq(*lhs, *rhs) } - fn ne(lhs: i16, rhs: i16) -> bool { - i16_ne(lhs, rhs) + fn ne(lhs: @i16, rhs: @i16) -> bool { + i16_ne(*lhs, *rhs) } } @@ -337,7 +337,7 @@ fn i16_div_rem(a: i16, b: i16) -> (i16, i16) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i16_eq(a: i16, b: i16) -> bool { // Check if the two integers have the same sign and the same absolute value. - if a.sign == b.sign & a.mag == b.mag { + if (a.sign == b.sign) & (a.mag == b.mag) { return true; } @@ -399,7 +399,7 @@ fn i16_lt(a: i16, b: i16) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i16_le(a: i16, b: i16) -> bool { - if (a == b | i16_lt(a, b) == true) { + if ((a == b) | (i16_lt(a, b) == true)) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i16_le(a: i16, b: i16) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i16_ge(a: i16, b: i16) -> bool { - if (a == b | i16_gt(a, b) == true) { + if ((a == b) | i16_gt(a, b) == true) { return true; } else { return false; diff --git a/src/numbers/signed_integer/i32.cairo b/src/numbers/signed_integer/i32.cairo index ece999a8e..f2beef3ce 100644 --- a/src/numbers/signed_integer/i32.cairo +++ b/src/numbers/signed_integer/i32.cairo @@ -126,12 +126,12 @@ impl i32RemEq of RemEq { // Implements the PartialEq trait for i32. impl i32PartialEq of PartialEq { - fn eq(lhs: i32, rhs: i32) -> bool { - i32_eq(lhs, rhs) + fn eq(lhs: @i32, rhs: @i32) -> bool { + i32_eq(*lhs, *rhs) } - fn ne(lhs: i32, rhs: i32) -> bool { - i32_ne(lhs, rhs) + fn ne(lhs: @i32, rhs: @i32) -> bool { + i32_ne(*lhs, *rhs) } } @@ -337,7 +337,7 @@ fn i32_div_rem(a: i32, b: i32) -> (i32, i32) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i32_eq(a: i32, b: i32) -> bool { // Check if the two integers have the same sign and the same absolute value. - if a.sign == b.sign & a.mag == b.mag { + if (a.sign == b.sign) & (a.mag == b.mag) { return true; } @@ -399,7 +399,7 @@ fn i32_lt(a: i32, b: i32) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i32_le(a: i32, b: i32) -> bool { - if (a == b | i32_lt(a, b) == true) { + if ((a == b) | (i32_lt(a, b) == true)) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i32_le(a: i32, b: i32) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i32_ge(a: i32, b: i32) -> bool { - if (a == b | i32_gt(a, b) == true) { + if ((a == b )| (i32_gt(a, b) == true)) { return true; } else { return false; diff --git a/src/numbers/signed_integer/i64.cairo b/src/numbers/signed_integer/i64.cairo index 3aabe7528..34fdf1fdd 100644 --- a/src/numbers/signed_integer/i64.cairo +++ b/src/numbers/signed_integer/i64.cairo @@ -126,12 +126,12 @@ impl i64RemEq of RemEq { // Implements the PartialEq trait for i64. impl i64PartialEq of PartialEq { - fn eq(lhs: i64, rhs: i64) -> bool { - i64_eq(lhs, rhs) + fn eq(lhs: @i64, rhs: @i64) -> bool { + i64_eq(*lhs, *rhs) } - fn ne(lhs: i64, rhs: i64) -> bool { - i64_ne(lhs, rhs) + fn ne(lhs: @i64, rhs: @i64) -> bool { + i64_ne(*lhs, *rhs) } } @@ -337,7 +337,7 @@ fn i64_div_rem(a: i64, b: i64) -> (i64, i64) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i64_eq(a: i64, b: i64) -> bool { // Check if the two integers have the same sign and the same absolute value. - if a.sign == b.sign & a.mag == b.mag { + if (a.sign == b.sign )& (a.mag == b.mag) { return true; } @@ -399,7 +399,7 @@ fn i64_lt(a: i64, b: i64) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i64_le(a: i64, b: i64) -> bool { - if (a == b | i64_lt(a, b) == true) { + if ((a == b) | (i64_lt(a, b) == true)) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i64_le(a: i64, b: i64) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i64_ge(a: i64, b: i64) -> bool { - if (a == b | i64_gt(a, b) == true) { + if ((a == b) | (i64_gt(a, b) == true)) { return true; } else { return false; diff --git a/src/numbers/signed_integer/i8.cairo b/src/numbers/signed_integer/i8.cairo index 84715449d..79f114eb2 100644 --- a/src/numbers/signed_integer/i8.cairo +++ b/src/numbers/signed_integer/i8.cairo @@ -126,12 +126,12 @@ impl i8RemEq of RemEq { // Implements the PartialEq trait for i8. impl i8PartialEq of PartialEq { - fn eq(lhs: i8, rhs: i8) -> bool { - i8_eq(lhs, rhs) + fn eq(lhs: @i8, rhs: @i8) -> bool { + i8_eq(*lhs, *rhs) } - fn ne(lhs: i8, rhs: i8) -> bool { - i8_ne(lhs, rhs) + fn ne(lhs: @i8, rhs: @i8) -> bool { + i8_ne(*lhs, *rhs) } } @@ -337,7 +337,7 @@ fn i8_div_rem(a: i8, b: i8) -> (i8, i8) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i8_eq(a: i8, b: i8) -> bool { // Check if the two integers have the same sign and the same absolute value. - if a.sign == b.sign & a.mag == b.mag { + if (a.sign == b.sign) & (a.mag == b.mag) { return true; } @@ -399,7 +399,7 @@ fn i8_lt(a: i8, b: i8) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i8_le(a: i8, b: i8) -> bool { - if (a == b | i8_lt(a, b) == true) { + if ((a == b) | (i8_lt(a, b) == true)) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i8_le(a: i8, b: i8) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i8_ge(a: i8, b: i8) -> bool { - if (a == b | i8_gt(a, b) == true) { + if ((a == b) | (i8_gt(a, b) == true)) { return true; } else { return false; diff --git a/src/operators/nn/core.cairo b/src/operators/nn/core.cairo index 0a973a745..da3c02120 100644 --- a/src/operators/nn/core.cairo +++ b/src/operators/nn/core.cairo @@ -37,7 +37,7 @@ trait NNTrait { /// /// ```rust /// use orion::operators::nn::core::NNTrait; - /// use orion::operators::nn::implementations::impl_nn_i32; + /// use orion::operators::nn::implementations::impl_nn_i32::NN_i32; /// /// fn relu_example() -> Tensor { /// // We instantiate a 2D Tensor here and set threshold to 0. @@ -77,7 +77,7 @@ trait NNTrait { /// /// ```rust /// use orion::operators::nn::core::NNTrait; - /// use orion::operators::nn::implementations::impl_nn_u32; + /// use orion::operators::nn::implementations::impl_nn_u32::NN_u32; /// /// fn softmax_example() -> Tensor { /// // We instantiate a 2D Tensor here. @@ -118,7 +118,7 @@ trait NNTrait { /// /// ```rust /// use orion::operators::nn::core::NNTrait; - /// use orion::operators::nn::implementations::impl_nn_u32; + /// use orion::operators::nn::implementations::impl_nn_u32::NN_u32; /// /// fn logsoftmax_example() -> Tensor { /// // We instantiate a 2D Tensor here. @@ -164,7 +164,7 @@ trait NNTrait { /// /// ```rust /// use orion::operators::nn::core::NNTrait; - /// use orion::operators::nn::implementations::impl_nn_u32; + /// use orion::operators::nn::implementations::impl_nn_u32::NN_u32; /// /// fn sigmoid_example() -> Tensor { /// // We instantiate a 2D Tensor here. @@ -204,7 +204,7 @@ trait NNTrait { /// /// ```rust /// use orion::operators::nn::core::NNTrait; - /// use orion::operators::nn::implementations::impl_nn_u32; + /// use orion::operators::nn::implementations::impl_nn_u32::NN_u32; /// /// fn softsign_example() -> Tensor { /// // We instantiate a 2D Tensor here. @@ -244,7 +244,7 @@ trait NNTrait { /// /// ```rust /// use orion::operators::nn::core::NNTrait; - /// use orion::operators::nn::implementations::impl_nn_u32; + /// use orion::operators::nn::implementations::impl_nn_u32::NN_u32; /// /// fn softplus_example() -> Tensor { /// // We instantiate a 2D Tensor here. @@ -287,7 +287,7 @@ trait NNTrait { /// /// ```rust /// use orion::operators::nn::core::NNTrait; - /// use orion::operators::nn::implementations::impl_nn_i32; + /// use orion::operators::nn::implementations::impl_nn_i32::NN_i32; /// /// fn linear_layer_example() -> Tensor { /// // We instantiate inputs here. @@ -335,7 +335,7 @@ trait NNTrait { /// /// ```rust /// use orion::operators::nn::core::NNTrait; - /// use orion::operators::nn::implementations::impl_nn_i32; + /// use orion::operators::nn::implementations::impl_nn_i32::NN_i32; /// /// fn leaky_relu_example() -> Tensor { /// // We instantiate a 2D Tensor here, the alpha and set threshold to 0. diff --git a/src/operators/nn/functional/leaky_relu/leaky_relu_i32/fp16x16.cairo b/src/operators/nn/functional/leaky_relu/leaky_relu_i32/fp16x16.cairo index 6b161c5e6..4f7ed92cb 100644 --- a/src/operators/nn/functional/leaky_relu/leaky_relu_i32/fp16x16.cairo +++ b/src/operators/nn/functional/leaky_relu/leaky_relu_i32/fp16x16.cairo @@ -4,18 +4,16 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, ONE, FP16x16Mul}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; /// Cf: NNTrait::leaky_relu docstring -fn leaky_relu( - z: @Tensor, alpha: @FixedType, threshold: i32 -) -> Tensor { - assert(*alpha.mag < impl_16x16::ONE, 'alpha must be less than 1_fp'); +fn leaky_relu(z: @Tensor, alpha: @FixedType, threshold: i32) -> Tensor { + assert(*alpha.mag < ONE, 'alpha must be less than 1_fp'); let mut data_result = ArrayTrait::::new(); let mut data = *z.data; diff --git a/src/operators/nn/functional/leaky_relu/leaky_relu_i32/fp8x23.cairo b/src/operators/nn/functional/leaky_relu/leaky_relu_i32/fp8x23.cairo index 7e8ee0ebb..ebfc3ea48 100644 --- a/src/operators/nn/functional/leaky_relu/leaky_relu_i32/fp8x23.cairo +++ b/src/operators/nn/functional/leaky_relu/leaky_relu_i32/fp8x23.cairo @@ -4,17 +4,15 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE, FP8x23Mul}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; /// Cf: NNTrait::leaky_relu docstring -fn leaky_relu( - z: @Tensor, alpha: @FixedType, threshold: i32 -) -> Tensor { - assert(*alpha.mag < impl_8x23::ONE, 'alpha must be less than 1_fp'); +fn leaky_relu(z: @Tensor, alpha: @FixedType, threshold: i32) -> Tensor { + assert(*alpha.mag < ONE, 'alpha must be less than 1_fp'); let mut data_result = ArrayTrait::::new(); let mut data = *z.data; diff --git a/src/operators/nn/functional/leaky_relu/leaky_relu_u32/fp16x16.cairo b/src/operators/nn/functional/leaky_relu/leaky_relu_u32/fp16x16.cairo index d3ef8dc6e..dc3dce52b 100644 --- a/src/operators/nn/functional/leaky_relu/leaky_relu_u32/fp16x16.cairo +++ b/src/operators/nn/functional/leaky_relu/leaky_relu_u32/fp16x16.cairo @@ -4,14 +4,14 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, ONE, FP16x16Mul}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; /// Cf: NNTrait::leaky_relu docstring fn leaky_relu(z: @Tensor, alpha: @FixedType, threshold: u32) -> Tensor { - assert(*alpha.mag < impl_16x16::ONE, 'alpha must be less than 1_fp'); + assert(*alpha.mag < ONE, 'alpha must be less than 1_fp'); let mut data_result = ArrayTrait::::new(); let mut data = *z.data; diff --git a/src/operators/nn/functional/leaky_relu/leaky_relu_u32/fp8x23.cairo b/src/operators/nn/functional/leaky_relu/leaky_relu_u32/fp8x23.cairo index 511bbda3b..f58321219 100644 --- a/src/operators/nn/functional/leaky_relu/leaky_relu_u32/fp8x23.cairo +++ b/src/operators/nn/functional/leaky_relu/leaky_relu_u32/fp8x23.cairo @@ -4,14 +4,14 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE, FP8x23Mul}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; /// Cf: NNTrait::leaky_relu docstring fn leaky_relu(z: @Tensor, alpha: @FixedType, threshold: u32) -> Tensor { - assert(*alpha.mag < impl_8x23::ONE, 'alpha must be less than 1_fp'); + assert(*alpha.mag < ONE, 'alpha must be less than 1_fp'); let mut data_result = ArrayTrait::::new(); let mut data = *z.data; diff --git a/src/operators/nn/functional/linear/linear_i32.cairo b/src/operators/nn/functional/linear/linear_i32.cairo index 98f6a38ac..a8c58f4f5 100644 --- a/src/operators/nn/functional/linear/linear_i32.cairo +++ b/src/operators/nn/functional/linear/linear_i32.cairo @@ -2,9 +2,9 @@ use array::SpanTrait; use orion::numbers::signed_integer::i32::i32; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::{Tensor_i32, i32TensorAdd}; use orion::performance::core::PerfomanceTrait; -use orion::performance::implementations::impl_performance_i32; +use orion::performance::implementations::impl_performance_i32::Performance_i32; /// Cf: NNTrait::linear docstring fn linear_i32( diff --git a/src/operators/nn/functional/linear/linear_u32.cairo b/src/operators/nn/functional/linear/linear_u32.cairo index a296c54d2..73a3a9254 100644 --- a/src/operators/nn/functional/linear/linear_u32.cairo +++ b/src/operators/nn/functional/linear/linear_u32.cairo @@ -1,9 +1,9 @@ use array::SpanTrait; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::{Tensor_u32, u32TensorAdd}; use orion::performance::core::PerfomanceTrait; -use orion::performance::implementations::impl_performance_u32; +use orion::performance::implementations::impl_performance_u32::Performance_i32; /// Cf: NNTrait::linear docstring fn linear_u32( diff --git a/src/operators/nn/functional/logsoftmax/logsoftmax_i32.cairo b/src/operators/nn/functional/logsoftmax/logsoftmax_i32.cairo index d7ae6a42e..8509ac337 100644 --- a/src/operators/nn/functional/logsoftmax/logsoftmax_i32.cairo +++ b/src/operators/nn/functional/logsoftmax/logsoftmax_i32.cairo @@ -1,7 +1,8 @@ use orion::numbers::signed_integer::i32::i32; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_i32, impl_tensor_fp}; - +use orion::operators::tensor::implementations::{ + impl_tensor_i32::Tensor_i32, impl_tensor_fp::{Tensor_fp, FixedTypeTensorDiv} +}; use orion::numbers::fixed_point::core::FixedType; /// Cf: NNTrait::logsoftmax docstring @@ -12,4 +13,4 @@ fn logsoftmax_i32(z: @Tensor, axis: usize) -> Tensor { let logsoftmax = softmax.ln(); return logsoftmax; -} \ No newline at end of file +} diff --git a/src/operators/nn/functional/logsoftmax/logsoftmax_u32.cairo b/src/operators/nn/functional/logsoftmax/logsoftmax_u32.cairo index 7c77857c7..fb86fcec7 100644 --- a/src/operators/nn/functional/logsoftmax/logsoftmax_u32.cairo +++ b/src/operators/nn/functional/logsoftmax/logsoftmax_u32.cairo @@ -1,6 +1,7 @@ use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_u32, impl_tensor_fp}; - +use orion::operators::tensor::implementations::{ + impl_tensor_u32::Tensor_u32, impl_tensor_fp::{Tensor_fp, FixedTypeTensorDiv} +}; use orion::numbers::fixed_point::core::FixedType; /// Cf: NNTrait::logsoftmax docstring @@ -11,4 +12,4 @@ fn logsoftmax_u32(z: @Tensor, axis: usize) -> Tensor { let logsoftmax = softmax.ln(); return logsoftmax; -} \ No newline at end of file +} diff --git a/src/operators/nn/functional/relu/relu_i32.cairo b/src/operators/nn/functional/relu/relu_i32.cairo index 32014deac..0af290737 100644 --- a/src/operators/nn/functional/relu/relu_i32.cairo +++ b/src/operators/nn/functional/relu/relu_i32.cairo @@ -4,7 +4,7 @@ use option::OptionTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::utils::check_gas; /// Cf: NNTrait::relu docstring diff --git a/src/operators/nn/functional/relu/relu_u32.cairo b/src/operators/nn/functional/relu/relu_u32.cairo index b6273f87f..bce10ec3e 100644 --- a/src/operators/nn/functional/relu/relu_u32.cairo +++ b/src/operators/nn/functional/relu/relu_u32.cairo @@ -3,7 +3,7 @@ use array::SpanTrait; use option::OptionTrait; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::utils::check_gas; /// Cf: NNTrait::relu docstring diff --git a/src/operators/nn/functional/sigmoid/sigmoid_i32/fp16x16.cairo b/src/operators/nn/functional/sigmoid/sigmoid_i32/fp16x16.cairo index fdd752812..1e97860c6 100644 --- a/src/operators/nn/functional/sigmoid/sigmoid_i32/fp16x16.cairo +++ b/src/operators/nn/functional/sigmoid/sigmoid_i32/fp16x16.cairo @@ -5,10 +5,9 @@ use array::SpanTrait; use option::OptionTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Add, FP16x16Div}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp;use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; use orion::utils::check_gas; /// Cf: NNTrait::sigmoid docstring diff --git a/src/operators/nn/functional/sigmoid/sigmoid_i32/fp8x23.cairo b/src/operators/nn/functional/sigmoid/sigmoid_i32/fp8x23.cairo index 554fa2188..0a0ddf1df 100644 --- a/src/operators/nn/functional/sigmoid/sigmoid_i32/fp8x23.cairo +++ b/src/operators/nn/functional/sigmoid/sigmoid_i32/fp8x23.cairo @@ -4,9 +4,9 @@ use array::SpanTrait; use option::OptionTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Add, FP8x23Div}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; use orion::utils::check_gas; diff --git a/src/operators/nn/functional/sigmoid/sigmoid_u32/fp16x16.cairo b/src/operators/nn/functional/sigmoid/sigmoid_u32/fp16x16.cairo index aa36cd536..862777e8a 100644 --- a/src/operators/nn/functional/sigmoid/sigmoid_u32/fp16x16.cairo +++ b/src/operators/nn/functional/sigmoid/sigmoid_u32/fp16x16.cairo @@ -3,9 +3,9 @@ use array::ArrayTrait; use array::SpanTrait; use option::OptionTrait; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Add, FP16x16Div}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; use orion::utils::check_gas; diff --git a/src/operators/nn/functional/sigmoid/sigmoid_u32/fp8x23.cairo b/src/operators/nn/functional/sigmoid/sigmoid_u32/fp8x23.cairo index 167b7f287..28aa97838 100644 --- a/src/operators/nn/functional/sigmoid/sigmoid_u32/fp8x23.cairo +++ b/src/operators/nn/functional/sigmoid/sigmoid_u32/fp8x23.cairo @@ -3,9 +3,9 @@ use array::ArrayTrait; use array::SpanTrait; use option::OptionTrait; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Add, FP8x23Div}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; use orion::utils::check_gas; diff --git a/src/operators/nn/functional/softmax/softmax_i32.cairo b/src/operators/nn/functional/softmax/softmax_i32.cairo index 8f247d795..074f65f30 100644 --- a/src/operators/nn/functional/softmax/softmax_i32.cairo +++ b/src/operators/nn/functional/softmax/softmax_i32.cairo @@ -1,7 +1,8 @@ use orion::numbers::signed_integer::i32::i32; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_i32, impl_tensor_fp}; - +use orion::operators::tensor::implementations::{ + impl_tensor_i32::Tensor_i32, impl_tensor_fp::{Tensor_fp, FixedTypeTensorDiv} +}; use orion::numbers::fixed_point::core::FixedType; /// Cf: NNTrait::softmax docstring diff --git a/src/operators/nn/functional/softmax/softmax_u32.cairo b/src/operators/nn/functional/softmax/softmax_u32.cairo index 62ff7b01d..1339308dd 100644 --- a/src/operators/nn/functional/softmax/softmax_u32.cairo +++ b/src/operators/nn/functional/softmax/softmax_u32.cairo @@ -1,6 +1,7 @@ use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_u32, impl_tensor_fp}; - +use orion::operators::tensor::implementations::{ + impl_tensor_u32::Tensor_u32, impl_tensor_fp::{Tensor_fp, FixedTypeTensorDiv} +}; use orion::numbers::fixed_point::core::FixedType; diff --git a/src/operators/nn/functional/softplus/softplus_i32/fp16x16.cairo b/src/operators/nn/functional/softplus/softplus_i32/fp16x16.cairo index 317349cf6..3225d52c8 100644 --- a/src/operators/nn/functional/softplus/softplus_i32/fp16x16.cairo +++ b/src/operators/nn/functional/softplus/softplus_i32/fp16x16.cairo @@ -5,9 +5,9 @@ use option::OptionTrait; use orion::numbers::signed_integer::i32::i32; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_fp}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Add, FP16x16Div}; use orion::utils::check_gas; /// Cf: NNTrait::softplus docstring diff --git a/src/operators/nn/functional/softplus/softplus_i32/fp8x23.cairo b/src/operators/nn/functional/softplus/softplus_i32/fp8x23.cairo index 0fab7ddac..f392049e4 100644 --- a/src/operators/nn/functional/softplus/softplus_i32/fp8x23.cairo +++ b/src/operators/nn/functional/softplus/softplus_i32/fp8x23.cairo @@ -5,9 +5,9 @@ use option::OptionTrait; use orion::numbers::signed_integer::i32::i32; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_fp}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Add, FP8x23Div}; use orion::utils::check_gas; diff --git a/src/operators/nn/functional/softplus/softplus_u32/fp16x16.cairo b/src/operators/nn/functional/softplus/softplus_u32/fp16x16.cairo index f0eab49b6..b4bfed025 100644 --- a/src/operators/nn/functional/softplus/softplus_u32/fp16x16.cairo +++ b/src/operators/nn/functional/softplus/softplus_u32/fp16x16.cairo @@ -5,9 +5,9 @@ use array::SpanTrait; use option::OptionTrait; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_fp}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Add, FP16x16Div}; use orion::utils::check_gas; diff --git a/src/operators/nn/functional/softplus/softplus_u32/fp8x23.cairo b/src/operators/nn/functional/softplus/softplus_u32/fp8x23.cairo index d85fce795..e7712fb7d 100644 --- a/src/operators/nn/functional/softplus/softplus_u32/fp8x23.cairo +++ b/src/operators/nn/functional/softplus/softplus_u32/fp8x23.cairo @@ -5,9 +5,9 @@ use array::SpanTrait; use option::OptionTrait; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_fp}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Add, FP8x23Div}; use orion::utils::check_gas; diff --git a/src/operators/nn/functional/softsign/softsign_i32/fp16x16.cairo b/src/operators/nn/functional/softsign/softsign_i32/fp16x16.cairo index 63632a364..63c5f4903 100644 --- a/src/operators/nn/functional/softsign/softsign_i32/fp16x16.cairo +++ b/src/operators/nn/functional/softsign/softsign_i32/fp16x16.cairo @@ -5,9 +5,9 @@ use option::OptionTrait; use orion::numbers::signed_integer::i32::i32; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_fp}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Add, FP16x16Div}; use orion::utils::check_gas; diff --git a/src/operators/nn/functional/softsign/softsign_i32/fp8x23.cairo b/src/operators/nn/functional/softsign/softsign_i32/fp8x23.cairo index 443bdc973..980757ead 100644 --- a/src/operators/nn/functional/softsign/softsign_i32/fp8x23.cairo +++ b/src/operators/nn/functional/softsign/softsign_i32/fp8x23.cairo @@ -5,9 +5,9 @@ use option::OptionTrait; use orion::numbers::signed_integer::i32::i32; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_fp}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Add, FP8x23Div}; use orion::utils::check_gas; diff --git a/src/operators/nn/functional/softsign/softsign_u32/fp16x16.cairo b/src/operators/nn/functional/softsign/softsign_u32/fp16x16.cairo index 375be2b72..601df84e4 100644 --- a/src/operators/nn/functional/softsign/softsign_u32/fp16x16.cairo +++ b/src/operators/nn/functional/softsign/softsign_u32/fp16x16.cairo @@ -4,9 +4,9 @@ use array::SpanTrait; use option::OptionTrait; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_fp}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Add, FP16x16Div}; use orion::utils::check_gas; /// Cf: NNTrait::softsign docstring diff --git a/src/operators/nn/functional/softsign/softsign_u32/fp8x23.cairo b/src/operators/nn/functional/softsign/softsign_u32/fp8x23.cairo index f65b11452..45d11ce0c 100644 --- a/src/operators/nn/functional/softsign/softsign_u32/fp8x23.cairo +++ b/src/operators/nn/functional/softsign/softsign_u32/fp8x23.cairo @@ -4,9 +4,9 @@ use array::SpanTrait; use option::OptionTrait; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::{impl_tensor_fp}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Add, FP8x23Div}; use orion::utils::check_gas; /// Cf: NNTrait::softsign docstring diff --git a/src/operators/tensor/helpers.cairo b/src/operators/tensor/helpers.cairo index 089fbd098..fb0383fba 100644 --- a/src/operators/tensor/helpers.cairo +++ b/src/operators/tensor/helpers.cairo @@ -65,7 +65,7 @@ fn check_compatibility(mut shape_1: Span, mut shape_2: Span) { let shape_2_val = *shape_2.pop_front().unwrap(); assert( - shape_1_val == shape_2_val | shape_1_val == 1 | shape_2_val == 1, + (shape_1_val == shape_2_val) | (shape_1_val == 1) | (shape_2_val == 1), 'tensors shape must match' ); }; @@ -291,7 +291,7 @@ fn broadcast_shape(mut shape1: Span, mut shape2: Span) -> Span { } /// Implements addition for `Tensor` using the `Add` trait. -impl U32TensorAdd of Add> { +impl u32TensorAdd of Add> { /// Adds two `Tensor` instances element-wise. /// /// # Arguments @@ -136,7 +136,7 @@ impl U32TensorAdd of Add> { } /// Implements subtraction for `Tensor` using the `Sub` trait. -impl U32TensorSub of Sub> { +impl u32TensorSub of Sub> { /// Subtracts two `Tensor` instances element-wise. /// /// # Arguments @@ -151,7 +151,7 @@ impl U32TensorSub of Sub> { } /// Implements multiplication for `Tensor` using the `Mul` trait. -impl U32TensorMul of Mul> { +impl u32TensorMul of Mul> { /// Multiplies two `Tensor` instances element-wise. /// /// # Arguments @@ -166,7 +166,7 @@ impl U32TensorMul of Mul> { } /// Implements division for `Tensor` using the `Div` trait. -impl U32TensorDiv of Div> { +impl u32TensorDiv of Div> { /// Divides two `Tensor` instances element-wise. /// /// # Arguments diff --git a/src/operators/tensor/linalg/matmul/helpers.cairo b/src/operators/tensor/linalg/matmul/helpers.cairo index f6e956a30..896da3ffa 100644 --- a/src/operators/tensor/linalg/matmul/helpers.cairo +++ b/src/operators/tensor/linalg/matmul/helpers.cairo @@ -24,7 +24,7 @@ use orion::utils::check_gas; fn prepare_shape_for_matmul(mut shape: Span, is_first_tensor: bool) -> Span { let ndim = shape.len(); - if ndim == 1 & is_first_tensor { + if (ndim == 1) & is_first_tensor { // Prepend 1 to shape if it's 1-dimensional let mut shape_adjusted = ArrayTrait::new(); shape_adjusted.append(1); @@ -37,7 +37,7 @@ fn prepare_shape_for_matmul(mut shape: Span, is_first_tensor: bool) -> Sp }; return shape_adjusted.span(); - } else if ndim == 1 & !is_first_tensor { + } else if (ndim == 1) & !is_first_tensor { // Append 1 to shape if it's 1-dimensional let mut shape_adjusted = ArrayTrait::new(); loop { diff --git a/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo b/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo index 99aec2a6b..8f072a60d 100644 --- a/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo +++ b/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo @@ -3,9 +3,10 @@ use array::SpanTrait; use option::OptionTrait; use orion::utils::check_gas; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::implementations::impl_16x16; - +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Mul, FP16x16AddEq +}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, ExtraParams, TensorTrait}; use orion::operators::tensor::linalg::matmul::helpers::{ @@ -19,10 +20,10 @@ fn matmul(self: @Tensor, other: @Tensor) -> Tensor, other: @Tensor) -> Tensor, other: @Tensor) -> Tensor { let self_ndim = (self_shape).len(); let other_ndim = (other_shape).len(); - assert(self_ndim <= 2 | other_ndim <= 2, 'supports only 1D and 2D matmul'); + assert((self_ndim <= 2) | (other_ndim <= 2), 'supports only 1D and 2D matmul'); //! Case: Both tensors are 1-dimensional - if self_ndim == 1 & other_ndim == 1 { + if (self_ndim == 1) & (other_ndim == 1) { let dot = dot_product((*self).data, (*other).data); let mut result_shape = ArrayTrait::new(); let mut result_data = ArrayTrait::new(); diff --git a/src/operators/tensor/linalg/matmul/matmul_u32.cairo b/src/operators/tensor/linalg/matmul/matmul_u32.cairo index 26bd4f1b1..ba9e1c95a 100644 --- a/src/operators/tensor/linalg/matmul/matmul_u32.cairo +++ b/src/operators/tensor/linalg/matmul/matmul_u32.cairo @@ -3,7 +3,7 @@ use array::SpanTrait; use option::OptionTrait; use orion::utils::check_gas; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, ExtraParams, TensorTrait, }; use orion::operators::tensor::linalg::matmul::helpers::{ prepare_shape_for_matmul, adjust_output_shape_after_matmul @@ -16,10 +16,10 @@ fn matmul(self: @Tensor, other: @Tensor) -> Tensor { let self_ndim = (self_shape).len(); let other_ndim = (other_shape).len(); - assert(self_ndim <= 2 | other_ndim <= 2, 'supports only 1D and 2D matmul'); + assert((self_ndim <= 2) | (other_ndim <= 2), 'supports only 1D and 2D matmul'); //! Case: Both tensors are 1-dimensional - if self_ndim == 1 & other_ndim == 1 { + if (self_ndim == 1) & (other_ndim == 1) { let dot = dot_product((*self).data, (*other).data); let mut result_shape = ArrayTrait::new(); let mut result_data = ArrayTrait::new(); diff --git a/src/operators/tensor/linalg/transpose/transpose_fp/core.cairo b/src/operators/tensor/linalg/transpose/transpose_fp/core.cairo index 3a37d8bf1..978b9066f 100644 --- a/src/operators/tensor/linalg/transpose/transpose_fp/core.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_fp/core.cairo @@ -1,6 +1,6 @@ use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; use orion::operators::tensor::core::Tensor; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::linalg::transpose::transpose_fp::fp8x23; use orion::operators::tensor::linalg::transpose::transpose_fp::fp16x16; use orion::utils::check_gas; diff --git a/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo b/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo index 02c3f1906..9a01aae5b 100644 --- a/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo @@ -6,8 +6,8 @@ use orion::operators::tensor::core::{ new_tensor, stride, Tensor, TensorTrait, ravel_index, unravel_index, reshape }; use orion::operators::tensor::helpers::{len_from_shape, find_axis, permutation_output_shape}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::utils::check_gas; /// Cf: TensorTrait::transpose docstring diff --git a/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo b/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo index 777527df4..b5f8aea4c 100644 --- a/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo @@ -6,8 +6,8 @@ use orion::operators::tensor::core::{ new_tensor, stride, Tensor, TensorTrait, ravel_index, unravel_index, reshape }; use orion::operators::tensor::helpers::{len_from_shape, find_axis, permutation_output_shape}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::utils::check_gas; /// Cf: TensorTrait::transpose docstring diff --git a/src/operators/tensor/linalg/transpose/transpose_i32.cairo b/src/operators/tensor/linalg/transpose/transpose_i32.cairo index 80e8c7da5..76d42644f 100644 --- a/src/operators/tensor/linalg/transpose/transpose_i32.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_i32.cairo @@ -6,7 +6,7 @@ use orion::operators::tensor::core::{ new_tensor, stride, Tensor, TensorTrait, ravel_index, unravel_index, reshape }; use orion::operators::tensor::helpers::{len_from_shape, find_axis, permutation_output_shape}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::utils::check_gas; /// Cf: TensorTrait::transpose docstring diff --git a/src/operators/tensor/linalg/transpose/transpose_u32.cairo b/src/operators/tensor/linalg/transpose/transpose_u32.cairo index 3dc14aa65..e6a777d68 100644 --- a/src/operators/tensor/linalg/transpose/transpose_u32.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_u32.cairo @@ -5,7 +5,7 @@ use orion::operators::tensor::core::{ new_tensor, stride, Tensor, TensorTrait, ravel_index, unravel_index, reshape }; use orion::operators::tensor::helpers::{len_from_shape, find_axis, permutation_output_shape}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::utils::check_gas; /// Cf: TensorTrait::transpose docstring diff --git a/src/operators/tensor/math/abs/abs_fp/core.cairo b/src/operators/tensor/math/abs/abs_fp/core.cairo index a999b562b..cb38af55a 100644 --- a/src/operators/tensor/math/abs/abs_fp/core.cairo +++ b/src/operators/tensor/math/abs/abs_fp/core.cairo @@ -1,5 +1,5 @@ use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::operators::tensor::math::abs::abs_fp::fp8x23; use orion::operators::tensor::math::abs::abs_fp::fp16x16; diff --git a/src/operators/tensor/math/abs/abs_fp/fp16x16.cairo b/src/operators/tensor/math/abs/abs_fp/fp16x16.cairo index 1f0237189..745b1ca35 100644 --- a/src/operators/tensor/math/abs/abs_fp/fp16x16.cairo +++ b/src/operators/tensor/math/abs/abs_fp/fp16x16.cairo @@ -3,9 +3,8 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/abs/abs_fp/fp8x23.cairo b/src/operators/tensor/math/abs/abs_fp/fp8x23.cairo index 15f25a296..2c109ae5c 100644 --- a/src/operators/tensor/math/abs/abs_fp/fp8x23.cairo +++ b/src/operators/tensor/math/abs/abs_fp/fp8x23.cairo @@ -3,9 +3,8 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/abs/abs_i32.cairo b/src/operators/tensor/math/abs/abs_i32.cairo index ce6a8b4d0..03067de39 100644 --- a/src/operators/tensor/math/abs/abs_i32.cairo +++ b/src/operators/tensor/math/abs/abs_i32.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/argmax/argmax_fp/fp16x16.cairo b/src/operators/tensor/math/argmax/argmax_fp/fp16x16.cairo index 5dd17b5c8..046933cc1 100644 --- a/src/operators/tensor/math/argmax/argmax_fp/fp16x16.cairo +++ b/src/operators/tensor/math/argmax/argmax_fp/fp16x16.cairo @@ -2,9 +2,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_16x16; - -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16PartialOrd, FP16x16PartialEq, MIN_MAG +}; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::operators::tensor::math::argmax::helpers::{find_argmax_1D, find_argmax}; @@ -12,12 +13,8 @@ use orion::utils::check_gas; /// Cf: TensorTrait::argmax docstring fn argmax( - self: @Tensor, - axis: usize, - keepdims: Option, - select_last_index:Option - ) -> Tensor { - + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option +) -> Tensor { let keepdims = match keepdims { Option::Some(val) => val, Option::None(_) => true, @@ -29,8 +26,8 @@ fn argmax( }; assert(axis <= (*self.shape).len(), 'axis out of dimensions'); - - if (*self.shape).len() == 1 { + + if (*self.shape).len() == 1 { return find_argmax_1D(self, axis, true, select_last_index); } @@ -38,17 +35,15 @@ fn argmax( let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); - - let MIN = FixedTrait::new(impl_16x16::MIN_MAG, true); + + let MIN = FixedTrait::new(MIN_MAG, true); let mut index: usize = 0; loop { check_gas(); let output_indices = unravel_index(index, output_shape); - let current_argmax = find_argmax( - self, output_indices, axis, 0, MIN, 0, select_last_index - ); + let current_argmax = find_argmax(self, output_indices, axis, 0, MIN, 0, select_last_index); output_data.append(current_argmax); @@ -58,5 +53,7 @@ fn argmax( }; }; - return TensorTrait::::new(reduce_output_shape(*self.shape, axis, keepdims), output_data.span(), *self.extra); + return TensorTrait::::new( + reduce_output_shape(*self.shape, axis, keepdims), output_data.span(), *self.extra + ); } diff --git a/src/operators/tensor/math/argmax/argmax_fp/fp8x23.cairo b/src/operators/tensor/math/argmax/argmax_fp/fp8x23.cairo index 9e0b2fd56..bcee3b4fc 100644 --- a/src/operators/tensor/math/argmax/argmax_fp/fp8x23.cairo +++ b/src/operators/tensor/math/argmax/argmax_fp/fp8x23.cairo @@ -2,9 +2,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_8x23; - -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Impl, FP8x23PartialOrd, FP8x23PartialEq, MIN_MAG +}; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::operators::tensor::math::argmax::helpers::{find_argmax_1D, find_argmax}; @@ -12,12 +13,8 @@ use orion::utils::check_gas; /// Cf: TensorTrait::argmax docstring fn argmax( - self: @Tensor, - axis: usize, - keepdims: Option, - select_last_index:Option - ) -> Tensor { - + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option +) -> Tensor { let keepdims = match keepdims { Option::Some(val) => val, Option::None(_) => true @@ -29,8 +26,8 @@ fn argmax( }; assert(axis <= (*self.shape).len(), 'axis out of dimensions'); - - if (*self.shape).len() == 1 { + + if (*self.shape).len() == 1 { return find_argmax_1D(self, axis, true, select_last_index); } @@ -38,17 +35,15 @@ fn argmax( let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); - - let MIN = FixedTrait::new(impl_8x23::MIN_MAG, true); + + let MIN = FixedTrait::new(MIN_MAG, true); let mut index: usize = 0; loop { check_gas(); let output_indices = unravel_index(index, output_shape); - let current_argmax = find_argmax( - self, output_indices, axis, 0, MIN, 0, select_last_index - ); + let current_argmax = find_argmax(self, output_indices, axis, 0, MIN, 0, select_last_index); output_data.append(current_argmax); @@ -58,5 +53,7 @@ fn argmax( }; }; - return TensorTrait::::new(reduce_output_shape(*self.shape, axis, keepdims), output_data.span(), *self.extra); + return TensorTrait::::new( + reduce_output_shape(*self.shape, axis, keepdims), output_data.span(), *self.extra + ); } diff --git a/src/operators/tensor/math/argmax/argmax_i32.cairo b/src/operators/tensor/math/argmax/argmax_i32.cairo index cd2599d77..f91d1bb33 100644 --- a/src/operators/tensor/math/argmax/argmax_i32.cairo +++ b/src/operators/tensor/math/argmax/argmax_i32.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::{impl_tensor_i32, impl_tensor_u32}; +use orion::operators::tensor::implementations::{impl_tensor_i32, impl_tensor_u32::Tensor_u32}; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::operators::tensor::math::argmax::helpers::{find_argmax_1D, find_argmax}; @@ -10,12 +10,8 @@ use orion::utils::check_gas; /// Cf: TensorTrait::argmax docstring fn argmax( - self: @Tensor, - axis: usize, - keepdims: Option, - select_last_index:Option - ) -> Tensor { - + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option +) -> Tensor { let keepdims = match keepdims { Option::Some(val) => val, Option::None(_) => true, @@ -25,10 +21,10 @@ fn argmax( Option::Some(val) => val, Option::None(_) => false, }; - + assert(axis <= (*self.shape).len(), 'axis out of dimensions'); - - if (*self.shape).len() == 1 { + + if (*self.shape).len() == 1 { return find_argmax_1D(self, axis, true, select_last_index); } @@ -44,10 +40,7 @@ fn argmax( check_gas(); let output_indices = unravel_index(index, output_shape); - let current_argmax = find_argmax( - self, output_indices, axis, 0, MIN , 0, select_last_index - - ); + let current_argmax = find_argmax(self, output_indices, axis, 0, MIN, 0, select_last_index); output_data.append(current_argmax); @@ -57,5 +50,7 @@ fn argmax( }; }; - return TensorTrait::::new(reduce_output_shape(*self.shape, axis, keepdims), output_data.span(), *self.extra); + return TensorTrait::::new( + reduce_output_shape(*self.shape, axis, keepdims), output_data.span(), *self.extra + ); } diff --git a/src/operators/tensor/math/argmax/argmax_u32.cairo b/src/operators/tensor/math/argmax/argmax_u32.cairo index 72cb38617..60fb0ef17 100644 --- a/src/operators/tensor/math/argmax/argmax_u32.cairo +++ b/src/operators/tensor/math/argmax/argmax_u32.cairo @@ -1,7 +1,7 @@ use array::ArrayTrait; use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::operators::tensor::math::argmax::helpers::{find_argmax_1D, find_argmax}; @@ -9,12 +9,8 @@ use orion::utils::check_gas; /// Cf: TensorTrait::argmax docstring fn argmax( - self: @Tensor, - axis: usize, - keepdims: Option, - select_last_index:Option - ) -> Tensor { - + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option +) -> Tensor { let keepdims = match keepdims { Option::Some(val) => val, Option::None(_) => true, @@ -24,10 +20,10 @@ fn argmax( Option::Some(val) => val, Option::None(_) => false, }; - + assert(axis <= (*self.shape).len(), 'axis out of dimensions'); - if (*self.shape).len() == 1 { + if (*self.shape).len() == 1 { return find_argmax_1D(self, axis, true, select_last_index); } @@ -41,9 +37,7 @@ fn argmax( check_gas(); let output_indices = unravel_index(index, output_shape); - let current_argmax = find_argmax( - self, output_indices, axis, 0, 0, 0, select_last_index - ); + let current_argmax = find_argmax(self, output_indices, axis, 0, 0, 0, select_last_index); output_data.append(current_argmax); @@ -53,5 +47,7 @@ fn argmax( }; }; - return TensorTrait::::new(reduce_output_shape(*self.shape, axis, keepdims), output_data.span(), *self.extra); + return TensorTrait::::new( + reduce_output_shape(*self.shape, axis, keepdims), output_data.span(), *self.extra + ); } diff --git a/src/operators/tensor/math/argmax/helpers.cairo b/src/operators/tensor/math/argmax/helpers.cairo index 43c64728c..39c0afac4 100644 --- a/src/operators/tensor/math/argmax/helpers.cairo +++ b/src/operators/tensor/math/argmax/helpers.cairo @@ -3,9 +3,9 @@ use array::ArrayTrait; use array::SpanTrait; use option::OptionTrait; -use orion::operators::tensor::implementations:: impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index}; -use orion::operators::tensor::helpers::{reduce_output_shape,combine_indices}; +use orion::operators::tensor::helpers::{reduce_output_shape, combine_indices}; use orion::utils::check_gas; /// Helper function that finds the index of the maximum value in a flat tensor. @@ -21,52 +21,49 @@ use orion::utils::check_gas; /// /// # Returns /// * A usize value representing the index of the maximum value along the specified axis. -fn find_argmax_1D< T, +fn find_argmax_1D< + T, impl TPartialOrd: PartialOrd, impl TPartialEq: PartialEq, impl TCopy: Copy, impl TDrop: Drop, >( - input: @Tensor, - axis: usize, - keepdims:bool, - select_last_index: bool - ) -> Tensor{ - - let mut output_data = ArrayTrait::::new(); - let mut data = *input.data; - - let mut max = *data.pop_front().unwrap(); - let mut max_index = 0_usize; - let mut count = 0_usize; - loop { - check_gas(); - - if data.len() == 0 { - break (); - }; + input: @Tensor, axis: usize, keepdims: bool, select_last_index: bool +) -> Tensor { + let mut output_data = ArrayTrait::::new(); + let mut data = *input.data; + + let mut max = *data.pop_front().unwrap(); + let mut max_index = 0_usize; + let mut count = 0_usize; + loop { + check_gas(); + + if data.len() == 0 { + break (); + }; - count += 1; + count += 1; - let current_value = *data.pop_front().unwrap(); - if current_value > max { - max = current_value; + let current_value = *data.pop_front().unwrap(); + if current_value > max { + max = current_value; + max_index = count; + } else { + if select_last_index & (current_value == max) { max_index = count; - - } else { - if select_last_index & (current_value == max) { - max_index = count; - } - }; + } }; + }; - output_data.append(max_index); + output_data.append(max_index); - return TensorTrait::::new(reduce_output_shape(*input.shape, axis, keepdims), output_data.span(), *input.extra); + return TensorTrait::::new( + reduce_output_shape(*input.shape, axis, keepdims), output_data.span(), *input.extra + ); } - /// Recursive helper function that finds the index of the maximum value along a specific axis. /// /// # Arguments @@ -83,7 +80,8 @@ fn find_argmax_1D< T, /// /// # Returns /// * A usize value representing the index of the maximum value along the specified axis. -fn find_argmax< T, +fn find_argmax< + T, impl TPartialOrd: PartialOrd, impl TPartialEq: PartialEq, impl TCopy: Copy, @@ -118,6 +116,12 @@ fn find_argmax< T, }; return find_argmax( - input, output_indices, axis, axis_index + 1_usize, new_max_value, new_argmax,select_last_index + input, + output_indices, + axis, + axis_index + 1_usize, + new_max_value, + new_argmax, + select_last_index ); } diff --git a/src/operators/tensor/math/argmin/argmin_fp/fp16x16.cairo b/src/operators/tensor/math/argmin/argmin_fp/fp16x16.cairo index 494f7c8aa..24728abbc 100644 --- a/src/operators/tensor/math/argmin/argmin_fp/fp16x16.cairo +++ b/src/operators/tensor/math/argmin/argmin_fp/fp16x16.cairo @@ -2,9 +2,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_16x16; - -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16PartialOrd, FP16x16PartialEq, MAX +}; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::operators::tensor::math::argmin::helpers::{find_argmin_1D,find_argmin}; @@ -40,7 +41,7 @@ fn argmin( let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); - let MAX = FixedTrait::new(impl_16x16::MAX , false); + let MAX = FixedTrait::new(MAX , false); let mut index: usize = 0; loop { diff --git a/src/operators/tensor/math/argmin/argmin_fp/fp8x23.cairo b/src/operators/tensor/math/argmin/argmin_fp/fp8x23.cairo index 3f68ca09c..f931d518c 100644 --- a/src/operators/tensor/math/argmin/argmin_fp/fp8x23.cairo +++ b/src/operators/tensor/math/argmin/argmin_fp/fp8x23.cairo @@ -1,9 +1,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_8x23; - -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Impl, FP8x23PartialOrd, FP8x23PartialEq, MAX +}; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::operators::tensor::math::argmin::helpers::{find_argmin_1D,find_argmin}; @@ -39,7 +40,7 @@ fn argmin( let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); - let MAX = FixedTrait::new(impl_8x23::MAX , false); + let MAX = FixedTrait::new(MAX , false); let mut index: usize = 0; loop { diff --git a/src/operators/tensor/math/argmin/argmin_i32.cairo b/src/operators/tensor/math/argmin/argmin_i32.cairo index 97b9505b9..2a5764723 100644 --- a/src/operators/tensor/math/argmin/argmin_i32.cairo +++ b/src/operators/tensor/math/argmin/argmin_i32.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::{impl_tensor_i32, impl_tensor_u32}; +use orion::operators::tensor::implementations::{impl_tensor_i32, impl_tensor_u32::Tensor_u32}; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::operators::tensor::math::argmin::helpers::{find_argmin_1D,find_argmin}; diff --git a/src/operators/tensor/math/argmin/argmin_u32.cairo b/src/operators/tensor/math/argmin/argmin_u32.cairo index 546e2dcf4..b5c09a384 100644 --- a/src/operators/tensor/math/argmin/argmin_u32.cairo +++ b/src/operators/tensor/math/argmin/argmin_u32.cairo @@ -1,7 +1,7 @@ use array::ArrayTrait; use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::operators::tensor::math::argmin::helpers::{find_argmin_1D,find_argmin}; diff --git a/src/operators/tensor/math/argmin/helpers.cairo b/src/operators/tensor/math/argmin/helpers.cairo index 7ce0161ce..52f9b9f4f 100644 --- a/src/operators/tensor/math/argmin/helpers.cairo +++ b/src/operators/tensor/math/argmin/helpers.cairo @@ -3,7 +3,7 @@ use array::ArrayTrait; use array::SpanTrait; use option::OptionTrait; -use orion::operators::tensor::implementations:: impl_tensor_u32; +use orion::operators::tensor::implementations:: impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape,combine_indices}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/arithmetic/arithmetic_fp/fp16x16.cairo b/src/operators/tensor/math/arithmetic/arithmetic_fp/fp16x16.cairo index 2ef089d22..63a72f60d 100644 --- a/src/operators/tensor/math/arithmetic/arithmetic_fp/fp16x16.cairo +++ b/src/operators/tensor/math/arithmetic/arithmetic_fp/fp16x16.cairo @@ -2,13 +2,13 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_16x16; - +use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Add, FP16x16Sub, FP16x16Mul, FP16x16Div +}; use orion::operators::tensor::helpers::broadcast_shape; - use orion::operators::tensor::core::{Tensor, TensorTrait, unravel_index, }; use orion::operators::tensor::helpers::{broadcast_index_mapping, len_from_shape, }; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::utils::check_gas; /// Adds two `Tensor` instances element-wise with broadcasting. diff --git a/src/operators/tensor/math/arithmetic/arithmetic_fp/fp8x23.cairo b/src/operators/tensor/math/arithmetic/arithmetic_fp/fp8x23.cairo index dac8de068..0721b4cd0 100644 --- a/src/operators/tensor/math/arithmetic/arithmetic_fp/fp8x23.cairo +++ b/src/operators/tensor/math/arithmetic/arithmetic_fp/fp8x23.cairo @@ -2,13 +2,13 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_8x23; - +use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Add, FP8x23Sub, FP8x23Mul, FP8x23Div +}; use orion::operators::tensor::helpers::broadcast_shape; - -use orion::operators::tensor::core::{Tensor, TensorTrait, unravel_index, }; +use orion::operators::tensor::core::{Tensor, TensorTrait, unravel_index}; use orion::operators::tensor::helpers::{broadcast_index_mapping, len_from_shape, }; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::utils::check_gas; /// Adds two `Tensor` instances element-wise with broadcasting. diff --git a/src/operators/tensor/math/arithmetic/arithmetic_i32.cairo b/src/operators/tensor/math/arithmetic/arithmetic_i32.cairo index e927eafd0..d223dc872 100644 --- a/src/operators/tensor/math/arithmetic/arithmetic_i32.cairo +++ b/src/operators/tensor/math/arithmetic/arithmetic_i32.cairo @@ -6,7 +6,7 @@ use orion::operators::tensor::helpers::broadcast_shape; use orion::operators::tensor::core::{Tensor, TensorTrait, unravel_index, }; use orion::operators::tensor::helpers::{broadcast_index_mapping, len_from_shape, }; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::utils::check_gas; /// Adds two `Tensor` instances element-wise with broadcasting. diff --git a/src/operators/tensor/math/arithmetic/arithmetic_u32.cairo b/src/operators/tensor/math/arithmetic/arithmetic_u32.cairo index b2782d893..8c09cbdfb 100644 --- a/src/operators/tensor/math/arithmetic/arithmetic_u32.cairo +++ b/src/operators/tensor/math/arithmetic/arithmetic_u32.cairo @@ -5,7 +5,7 @@ use orion::operators::tensor::helpers::broadcast_shape; use orion::operators::tensor::core::{Tensor, TensorTrait, unravel_index, }; use orion::operators::tensor::helpers::{broadcast_index_mapping, len_from_shape, }; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::utils::check_gas; /// Adds two `Tensor` instances element-wise with broadcasting. diff --git a/src/operators/tensor/math/ceil/ceil_fp/core.cairo b/src/operators/tensor/math/ceil/ceil_fp/core.cairo index 37337d493..2b2bfd625 100644 --- a/src/operators/tensor/math/ceil/ceil_fp/core.cairo +++ b/src/operators/tensor/math/ceil/ceil_fp/core.cairo @@ -1,5 +1,5 @@ use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::operators::tensor::math::ceil::ceil_fp::fp8x23; use orion::operators::tensor::math::ceil::ceil_fp::fp16x16; diff --git a/src/operators/tensor/math/ceil/ceil_fp/fp16x16.cairo b/src/operators/tensor/math/ceil/ceil_fp/fp16x16.cairo index 1d11f3043..55d3dadcc 100644 --- a/src/operators/tensor/math/ceil/ceil_fp/fp16x16.cairo +++ b/src/operators/tensor/math/ceil/ceil_fp/fp16x16.cairo @@ -2,8 +2,8 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/ceil/ceil_fp/fp8x23.cairo b/src/operators/tensor/math/ceil/ceil_fp/fp8x23.cairo index 57e9e2411..9ccf0fd32 100644 --- a/src/operators/tensor/math/ceil/ceil_fp/fp8x23.cairo +++ b/src/operators/tensor/math/ceil/ceil_fp/fp8x23.cairo @@ -2,8 +2,8 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/equal/equal_fp/fp16x16.cairo b/src/operators/tensor/math/equal/equal_fp/fp16x16.cairo index 0ff259905..bd125e995 100644 --- a/src/operators/tensor/math/equal/equal_fp/fp16x16.cairo +++ b/src/operators/tensor/math/equal/equal_fp/fp16x16.cairo @@ -3,9 +3,9 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_16x16; -use orion::operators::tensor::implementations::impl_tensor_u32; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16PartialEq; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/equal/equal_fp/fp8x23.cairo b/src/operators/tensor/math/equal/equal_fp/fp8x23.cairo index b6338123c..1a20386cd 100644 --- a/src/operators/tensor/math/equal/equal_fp/fp8x23.cairo +++ b/src/operators/tensor/math/equal/equal_fp/fp8x23.cairo @@ -3,9 +3,9 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_8x23; -use orion::operators::tensor::implementations::impl_tensor_u32; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23PartialEq; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/equal/equal_i32.cairo b/src/operators/tensor/math/equal/equal_i32.cairo index c04092722..1eb6789ce 100644 --- a/src/operators/tensor/math/equal/equal_i32.cairo +++ b/src/operators/tensor/math/equal/equal_i32.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/equal/equal_u32.cairo b/src/operators/tensor/math/equal/equal_u32.cairo index c31fba587..c3dc4812b 100644 --- a/src/operators/tensor/math/equal/equal_u32.cairo +++ b/src/operators/tensor/math/equal/equal_u32.cairo @@ -1,7 +1,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/exp/exp_fp/fp16x16.cairo b/src/operators/tensor/math/exp/exp_fp/fp16x16.cairo index d156b3b24..ddad3d01c 100644 --- a/src/operators/tensor/math/exp/exp_fp/fp16x16.cairo +++ b/src/operators/tensor/math/exp/exp_fp/fp16x16.cairo @@ -4,9 +4,8 @@ use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::utils::check_gas; /// Cf: TensorTrait::exp docstring diff --git a/src/operators/tensor/math/exp/exp_fp/fp8x23.cairo b/src/operators/tensor/math/exp/exp_fp/fp8x23.cairo index 5647d8e76..98418fef6 100644 --- a/src/operators/tensor/math/exp/exp_fp/fp8x23.cairo +++ b/src/operators/tensor/math/exp/exp_fp/fp8x23.cairo @@ -4,9 +4,8 @@ use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::utils::check_gas; /// Cf: TensorTrait::exp docstring diff --git a/src/operators/tensor/math/exp/exp_i32/fp16x16.cairo b/src/operators/tensor/math/exp/exp_i32/fp16x16.cairo index 9d281aa87..d5d52d5a4 100644 --- a/src/operators/tensor/math/exp/exp_i32/fp16x16.cairo +++ b/src/operators/tensor/math/exp/exp_i32/fp16x16.cairo @@ -6,9 +6,8 @@ use traits::Into; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::utils::check_gas; /// Cf: TensorTrait::exp docstring diff --git a/src/operators/tensor/math/exp/exp_i32/fp8x23.cairo b/src/operators/tensor/math/exp/exp_i32/fp8x23.cairo index 5c93ef68a..caf099e98 100644 --- a/src/operators/tensor/math/exp/exp_i32/fp8x23.cairo +++ b/src/operators/tensor/math/exp/exp_i32/fp8x23.cairo @@ -6,9 +6,8 @@ use traits::Into; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::utils::check_gas; /// Cf: TensorTrait::exp docstring diff --git a/src/operators/tensor/math/exp/exp_u32/fp16x16.cairo b/src/operators/tensor/math/exp/exp_u32/fp16x16.cairo index 5fd157753..2c8fb54f7 100644 --- a/src/operators/tensor/math/exp/exp_u32/fp16x16.cairo +++ b/src/operators/tensor/math/exp/exp_u32/fp16x16.cairo @@ -6,9 +6,8 @@ use traits::Into; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::utils::check_gas; /// Cf: TensorTrait::exp docstring diff --git a/src/operators/tensor/math/exp/exp_u32/fp8x23.cairo b/src/operators/tensor/math/exp/exp_u32/fp8x23.cairo index f7eb9bdb1..ccc60755a 100644 --- a/src/operators/tensor/math/exp/exp_u32/fp8x23.cairo +++ b/src/operators/tensor/math/exp/exp_u32/fp8x23.cairo @@ -6,9 +6,8 @@ use traits::Into; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::utils::check_gas; /// Cf: TensorTrait::exp docstring diff --git a/src/operators/tensor/math/greater/greater_fp/fp16x16.cairo b/src/operators/tensor/math/greater/greater_fp/fp16x16.cairo index f8df675bc..2c8024c7b 100644 --- a/src/operators/tensor/math/greater/greater_fp/fp16x16.cairo +++ b/src/operators/tensor/math/greater/greater_fp/fp16x16.cairo @@ -3,8 +3,8 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_16x16; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16PartialOrd; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; @@ -12,20 +12,19 @@ use orion::operators::tensor::helpers::check_compatibility; /// Cf: TensorTrait::greater docstring fn greater(y: @Tensor, z: @Tensor) -> Tensor { - - check_compatibility(*y.shape,*z.shape); + check_compatibility(*y.shape, *z.shape); let mut data_result = ArrayTrait::::new(); - let (mut smaller, mut bigger, retains_input_order) = if (*y.data).len() < (*z.data).len() { - (y, z, true) - } else { + let (mut smaller, mut bigger, retains_input_order) = if (*y.data).len() < (*z.data).len() { + (y, z, true) + } else { (z, y, false) }; let mut bigger_data = *bigger.data; let mut smaller_data = *smaller.data; let mut smaller_index = 0; - + loop { check_gas(); @@ -41,15 +40,15 @@ fn greater(y: @Tensor, z: @Tensor) -> Tensor { } else { (bigger_current_index, smaller_current_index) }; - + if y_value > z_value { data_result.append(1); } else { data_result.append(0); }; - - smaller_index = (1 + smaller_index) % smaller_data.len() ; + + smaller_index = (1 + smaller_index) % smaller_data.len(); }; return TensorTrait::::new(*bigger.shape, data_result.span(), *y.extra); -} \ No newline at end of file +} diff --git a/src/operators/tensor/math/greater/greater_fp/fp8x23.cairo b/src/operators/tensor/math/greater/greater_fp/fp8x23.cairo index fd82717c2..9364f2d6c 100644 --- a/src/operators/tensor/math/greater/greater_fp/fp8x23.cairo +++ b/src/operators/tensor/math/greater/greater_fp/fp8x23.cairo @@ -3,8 +3,8 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_8x23; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23PartialOrd; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/greater/greater_i32.cairo b/src/operators/tensor/math/greater/greater_i32.cairo index e3bf754b8..ba1937587 100644 --- a/src/operators/tensor/math/greater/greater_i32.cairo +++ b/src/operators/tensor/math/greater/greater_i32.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/greater/greater_u32.cairo b/src/operators/tensor/math/greater/greater_u32.cairo index 233c915d6..3d8a4e238 100644 --- a/src/operators/tensor/math/greater/greater_u32.cairo +++ b/src/operators/tensor/math/greater/greater_u32.cairo @@ -1,7 +1,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/greater_equal/greater_equal_fp/fp16x16.cairo b/src/operators/tensor/math/greater_equal/greater_equal_fp/fp16x16.cairo index 4711e7143..9e9ed22cd 100644 --- a/src/operators/tensor/math/greater_equal/greater_equal_fp/fp16x16.cairo +++ b/src/operators/tensor/math/greater_equal/greater_equal_fp/fp16x16.cairo @@ -3,8 +3,8 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_16x16; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16PartialOrd; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/greater_equal/greater_equal_fp/fp8x23.cairo b/src/operators/tensor/math/greater_equal/greater_equal_fp/fp8x23.cairo index 0904a0282..041c471bf 100644 --- a/src/operators/tensor/math/greater_equal/greater_equal_fp/fp8x23.cairo +++ b/src/operators/tensor/math/greater_equal/greater_equal_fp/fp8x23.cairo @@ -3,8 +3,8 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_8x23; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23PartialOrd; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/greater_equal/greater_equal_i32.cairo b/src/operators/tensor/math/greater_equal/greater_equal_i32.cairo index 4db3cacf4..855932a36 100644 --- a/src/operators/tensor/math/greater_equal/greater_equal_i32.cairo +++ b/src/operators/tensor/math/greater_equal/greater_equal_i32.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/greater_equal/greater_equal_u32.cairo b/src/operators/tensor/math/greater_equal/greater_equal_u32.cairo index 47434b2fb..f030e89c1 100644 --- a/src/operators/tensor/math/greater_equal/greater_equal_u32.cairo +++ b/src/operators/tensor/math/greater_equal/greater_equal_u32.cairo @@ -1,7 +1,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/less/less_fp/fp16x16.cairo b/src/operators/tensor/math/less/less_fp/fp16x16.cairo index f6cf711d6..4e9dc16d2 100644 --- a/src/operators/tensor/math/less/less_fp/fp16x16.cairo +++ b/src/operators/tensor/math/less/less_fp/fp16x16.cairo @@ -3,8 +3,8 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_16x16; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16PartialOrd; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/less/less_fp/fp8x23.cairo b/src/operators/tensor/math/less/less_fp/fp8x23.cairo index de9cfe035..fbebe1d6e 100644 --- a/src/operators/tensor/math/less/less_fp/fp8x23.cairo +++ b/src/operators/tensor/math/less/less_fp/fp8x23.cairo @@ -3,8 +3,8 @@ use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_8x23; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23PartialOrd; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/less/less_i32.cairo b/src/operators/tensor/math/less/less_i32.cairo index d1859d8ff..ca31dc6b0 100644 --- a/src/operators/tensor/math/less/less_i32.cairo +++ b/src/operators/tensor/math/less/less_i32.cairo @@ -3,7 +3,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/less/less_u32.cairo b/src/operators/tensor/math/less/less_u32.cairo index d15136ce6..8db1299e9 100644 --- a/src/operators/tensor/math/less/less_u32.cairo +++ b/src/operators/tensor/math/less/less_u32.cairo @@ -1,7 +1,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/less_equal/less_equal_fp/fp16x16.cairo b/src/operators/tensor/math/less_equal/less_equal_fp/fp16x16.cairo index 5a11568f3..56b9217ba 100644 --- a/src/operators/tensor/math/less_equal/less_equal_fp/fp16x16.cairo +++ b/src/operators/tensor/math/less_equal/less_equal_fp/fp16x16.cairo @@ -2,9 +2,8 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_16x16; - -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16PartialOrd; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/less_equal/less_equal_fp/fp8x23.cairo b/src/operators/tensor/math/less_equal/less_equal_fp/fp8x23.cairo index 0c573fe86..93a4dda2b 100644 --- a/src/operators/tensor/math/less_equal/less_equal_fp/fp8x23.cairo +++ b/src/operators/tensor/math/less_equal/less_equal_fp/fp8x23.cairo @@ -2,9 +2,8 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::FixedType; -use orion::numbers::fixed_point::implementations::impl_8x23; - -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23PartialOrd; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/less_equal/less_equal_i32.cairo b/src/operators/tensor/math/less_equal/less_equal_i32.cairo index cc7bf8030..bd82d7616 100644 --- a/src/operators/tensor/math/less_equal/less_equal_i32.cairo +++ b/src/operators/tensor/math/less_equal/less_equal_i32.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/less_equal/less_equal_u32.cairo b/src/operators/tensor/math/less_equal/less_equal_u32.cairo index d171aa244..a2bc4f093 100644 --- a/src/operators/tensor/math/less_equal/less_equal_u32.cairo +++ b/src/operators/tensor/math/less_equal/less_equal_u32.cairo @@ -1,7 +1,7 @@ use array::ArrayTrait; use option::OptionTrait; use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::utils::check_gas; use orion::operators::tensor::helpers::check_compatibility; diff --git a/src/operators/tensor/math/ln/ln_fp/fp16x16.cairo b/src/operators/tensor/math/ln/ln_fp/fp16x16.cairo index b11f7e886..e412c46a9 100644 --- a/src/operators/tensor/math/ln/ln_fp/fp16x16.cairo +++ b/src/operators/tensor/math/ln/ln_fp/fp16x16.cairo @@ -4,9 +4,8 @@ use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::utils::check_gas; /// Cf: TensorTrait::ln docstring diff --git a/src/operators/tensor/math/ln/ln_fp/fp8x23.cairo b/src/operators/tensor/math/ln/ln_fp/fp8x23.cairo index 2fe4a7250..19bb29e3d 100644 --- a/src/operators/tensor/math/ln/ln_fp/fp8x23.cairo +++ b/src/operators/tensor/math/ln/ln_fp/fp8x23.cairo @@ -4,9 +4,8 @@ use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::utils::check_gas; /// Cf: TensorTrait::ln docstring diff --git a/src/operators/tensor/math/ln/ln_i32/fp16x16.cairo b/src/operators/tensor/math/ln/ln_i32/fp16x16.cairo index a3b26f341..e92f3303b 100644 --- a/src/operators/tensor/math/ln/ln_i32/fp16x16.cairo +++ b/src/operators/tensor/math/ln/ln_i32/fp16x16.cairo @@ -6,9 +6,8 @@ use traits::Into; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::utils::check_gas; /// Cf: TensorTrait::ln docstring diff --git a/src/operators/tensor/math/ln/ln_i32/fp8x23.cairo b/src/operators/tensor/math/ln/ln_i32/fp8x23.cairo index 6197e173d..e22b5388b 100644 --- a/src/operators/tensor/math/ln/ln_i32/fp8x23.cairo +++ b/src/operators/tensor/math/ln/ln_i32/fp8x23.cairo @@ -6,9 +6,8 @@ use traits::Into; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::utils::check_gas; /// Cf: TensorTrait::ln docstring diff --git a/src/operators/tensor/math/ln/ln_u32/fp16x16.cairo b/src/operators/tensor/math/ln/ln_u32/fp16x16.cairo index 7054d06e4..68d15ee85 100644 --- a/src/operators/tensor/math/ln/ln_u32/fp16x16.cairo +++ b/src/operators/tensor/math/ln/ln_u32/fp16x16.cairo @@ -6,9 +6,9 @@ use traits::Into; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::utils::check_gas; /// Cf: TensorTrait::ln docstring diff --git a/src/operators/tensor/math/ln/ln_u32/fp8x23.cairo b/src/operators/tensor/math/ln/ln_u32/fp8x23.cairo index 31aef2a8d..d9c8b3405 100644 --- a/src/operators/tensor/math/ln/ln_u32/fp8x23.cairo +++ b/src/operators/tensor/math/ln/ln_u32/fp8x23.cairo @@ -6,9 +6,8 @@ use traits::Into; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; use orion::numbers::signed_integer::i32::i32; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::utils::check_gas; /// Cf: TensorTrait::ln docstring diff --git a/src/operators/tensor/math/max/max_fp/fp16x16.cairo b/src/operators/tensor/math/max/max_fp/fp16x16.cairo index ab62a711e..3c72fe87a 100644 --- a/src/operators/tensor/math/max/max_fp/fp16x16.cairo +++ b/src/operators/tensor/math/max/max_fp/fp16x16.cairo @@ -2,13 +2,13 @@ use array::SpanTrait; use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, MAX, FP16x16PartialOrd}; use orion::numbers::fixed_point::math::math_16x16::max; use orion::utils::check_gas; /// Cf: TensorTrait::max docstring fn max_in_tensor(mut vec: Span::) -> FixedType { - let mut max_value: FixedType = FixedTrait::new(impl_16x16::MAX, true); + let mut max_value: FixedType = FixedTrait::new(MAX, true); loop { check_gas(); diff --git a/src/operators/tensor/math/max/max_fp/fp8x23.cairo b/src/operators/tensor/math/max/max_fp/fp8x23.cairo index 6eee94c54..7eef6d7cf 100644 --- a/src/operators/tensor/math/max/max_fp/fp8x23.cairo +++ b/src/operators/tensor/math/max/max_fp/fp8x23.cairo @@ -2,14 +2,13 @@ use array::SpanTrait; use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_8x23; - +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, MAX, FP8x23PartialOrd}; use orion::numbers::fixed_point::math::math_8x23::max; use orion::utils::check_gas; /// Cf: TensorTrait::max docstring fn max_in_tensor(mut vec: Span::) -> FixedType { - let mut max_value: FixedType = FixedTrait::new(impl_8x23::MAX, true); + let mut max_value: FixedType = FixedTrait::new(MAX, true); loop { check_gas(); diff --git a/src/operators/tensor/math/min/min_fp/fp16x16.cairo b/src/operators/tensor/math/min/min_fp/fp16x16.cairo index ce8d0625c..d35f7db84 100644 --- a/src/operators/tensor/math/min/min_fp/fp16x16.cairo +++ b/src/operators/tensor/math/min/min_fp/fp16x16.cairo @@ -2,14 +2,13 @@ use array::SpanTrait; use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_16x16; - +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, MAX, FP16x16PartialOrd}; use orion::numbers::fixed_point::math::math_16x16::min; use orion::utils::check_gas; /// Cf: TensorTrait::min docstring fn min_in_tensor(mut vec: Span::) -> FixedType { - let mut min_value: FixedType = FixedTrait::new(impl_16x16::MAX - 1, false); + let mut min_value: FixedType = FixedTrait::new(MAX - 1, false); loop { check_gas(); diff --git a/src/operators/tensor/math/min/min_fp/fp8x23.cairo b/src/operators/tensor/math/min/min_fp/fp8x23.cairo index 1e91ceb1a..8a2165bf4 100644 --- a/src/operators/tensor/math/min/min_fp/fp8x23.cairo +++ b/src/operators/tensor/math/min/min_fp/fp8x23.cairo @@ -2,14 +2,13 @@ use array::SpanTrait; use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_8x23; - +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, MAX, FP8x23PartialOrd}; use orion::numbers::fixed_point::math::math_8x23::min; use orion::utils::check_gas; /// Cf: TensorTrait::min docstring fn min_in_tensor(mut vec: Span::) -> FixedType { - let mut min_value: FixedType = FixedTrait::new(impl_8x23::MAX - 1, false); + let mut min_value: FixedType = FixedTrait::new(MAX - 1, false); loop { check_gas(); diff --git a/src/operators/tensor/math/min/min_u32.cairo b/src/operators/tensor/math/min/min_u32.cairo index e17b1bb88..a99356775 100644 --- a/src/operators/tensor/math/min/min_u32.cairo +++ b/src/operators/tensor/math/min/min_u32.cairo @@ -1,7 +1,7 @@ use array::SpanTrait; use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::utils::check_gas; /// Cf: TensorTrait::min docstring diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo index 734eab124..0032287b9 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo @@ -3,17 +3,15 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16AddEq}; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::utils::check_gas; /// Cf: TensorTrait::reduce_sum docstring -fn reduce_sum( - self: @Tensor, axis: usize, keepdims: bool -) -> Tensor { +fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let mut output_data = ArrayTrait::new(); diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo index c35e9217f..c2087b279 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo @@ -3,17 +3,15 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23AddEq}; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::utils::check_gas; /// Cf: TensorTrait::reduce_sum docstring -fn reduce_sum( - self: @Tensor, axis: usize, keepdims: bool -) -> Tensor { +fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let mut output_data = ArrayTrait::new(); diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo index f92f37582..27ff5e8f2 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo @@ -3,7 +3,7 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::utils::check_gas; diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo index 1c2e8545d..547c2f07c 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use array::SpanTrait; use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; use orion::operators::tensor::helpers::{reduce_output_shape, len_from_shape, combine_indices}; use orion::utils::check_gas; diff --git a/src/performance/functional/quantization/quant_fp/fp16x16.cairo b/src/performance/functional/quantization/quant_fp/fp16x16.cairo index 37a2a7cf2..10793eb8b 100644 --- a/src/performance/functional/quantization/quant_fp/fp16x16.cairo +++ b/src/performance/functional/quantization/quant_fp/fp16x16.cairo @@ -6,9 +6,10 @@ use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::math::math_16x16::max; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Mul, FP16x16Div, FP16x16Sub +}; use orion::utils::check_gas; diff --git a/src/performance/functional/quantization/quant_fp/fp8x23.cairo b/src/performance/functional/quantization/quant_fp/fp8x23.cairo index 9bcb2bd8a..c3e4dc653 100644 --- a/src/performance/functional/quantization/quant_fp/fp8x23.cairo +++ b/src/performance/functional/quantization/quant_fp/fp8x23.cairo @@ -6,9 +6,10 @@ use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::math::math_8x23::max; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Impl, FP8x23Mul, FP8x23Div, FP8x23Sub +}; use orion::utils::check_gas; diff --git a/src/performance/functional/quantization/quant_i32.cairo b/src/performance/functional/quantization/quant_i32.cairo index 3f19086bd..e5e9e2b73 100644 --- a/src/performance/functional/quantization/quant_i32.cairo +++ b/src/performance/functional/quantization/quant_i32.cairo @@ -6,8 +6,8 @@ use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::performance::functional::quantization::quant_fp::core::symetric_quant as symetric_quant_fp; use orion::utils::check_gas; use orion::utils::fp8x23_to_i32; diff --git a/src/performance/functional/quantization/quant_u32.cairo b/src/performance/functional/quantization/quant_u32.cairo index 71015fbaf..ff282a21d 100644 --- a/src/performance/functional/quantization/quant_u32.cairo +++ b/src/performance/functional/quantization/quant_u32.cairo @@ -5,8 +5,8 @@ use option::OptionTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::operators::tensor::core::{Tensor, TensorTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::performance::functional::quantization::quant_fp::core::symetric_quant as symetric_quant_fp; use orion::utils::u32_max; use orion::utils::check_gas; diff --git a/src/performance/implementations/impl_performance_i32.cairo b/src/performance/implementations/impl_performance_i32.cairo index fa133d454..ea210fa53 100644 --- a/src/performance/implementations/impl_performance_i32.cairo +++ b/src/performance/implementations/impl_performance_i32.cairo @@ -7,7 +7,7 @@ use orion::performance::functional::quantization::quant_i32::{ quantize_tensor, quantize_fp_tensor }; -impl Performance_i32_fp of PerfomanceTrait { +impl Performance_i32 of PerfomanceTrait { fn quantize_linear(self: @Tensor) -> Tensor { quantize_tensor(self) } diff --git a/src/performance/implementations/impl_performance_u32.cairo b/src/performance/implementations/impl_performance_u32.cairo index ff43129fc..91b888120 100644 --- a/src/performance/implementations/impl_performance_u32.cairo +++ b/src/performance/implementations/impl_performance_u32.cairo @@ -4,7 +4,7 @@ use orion::operators::tensor::core::Tensor; use orion::performance::core::PerfomanceTrait; use orion::performance::functional::quantization::quant_u32::{quantize_tensor, quantize_fp_tensor}; -impl Performance_i32_fp of PerfomanceTrait { +impl Performance_i32 of PerfomanceTrait { fn quantize_linear(self: @Tensor) -> Tensor { quantize_tensor(self) } diff --git a/src/tests/numbers/fixed_point/fp16x16_test.cairo b/src/tests/numbers/fixed_point/fp16x16_test.cairo index a563c4df6..ec1233693 100644 --- a/src/tests/numbers/fixed_point/fp16x16_test.cairo +++ b/src/tests/numbers/fixed_point/fp16x16_test.cairo @@ -1,8 +1,11 @@ use option::OptionTrait; use traits::Into; -use orion::numbers::fixed_point::implementations::impl_16x16::{ONE, _felt_abs, _felt_sign}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{ + ONE, _felt_abs, _felt_sign, FP16x16Impl, FP16x16Into, FP16x16Add, FP16x16AddEq, FP16x16Sub, + FP16x16SubEq, FP16x16Mul, FP16x16MulEq, FP16x16Div, FP16x16DivEq, FP16x16PartialOrd, + FP16x16PartialEq +}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::core; diff --git a/src/tests/numbers/fixed_point/fp8x23_test.cairo b/src/tests/numbers/fixed_point/fp8x23_test.cairo index 880567235..a7d60c7c6 100644 --- a/src/tests/numbers/fixed_point/fp8x23_test.cairo +++ b/src/tests/numbers/fixed_point/fp8x23_test.cairo @@ -2,9 +2,10 @@ use option::OptionTrait; use traits::Into; -use orion::numbers::fixed_point::implementations::impl_8x23::{ONE, _felt_abs, _felt_sign}; - -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{ + ONE, _felt_abs, _felt_sign, FP8x23Impl, FP8x23Into, FP8x23Add, FP8x23AddEq, FP8x23Sub, + FP8x23SubEq, FP8x23Mul, FP8x23MulEq, FP8x23Div, FP8x23DivEq, FP8x23PartialOrd, FP8x23PartialEq +}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::core; diff --git a/src/tests/numbers/signed_integer_test.cairo b/src/tests/numbers/signed_integer_test.cairo index 480b44327..4c92cb2f7 100644 --- a/src/tests/numbers/signed_integer_test.cairo +++ b/src/tests/numbers/signed_integer_test.cairo @@ -191,34 +191,34 @@ fn test_div_rem() { let a = IntegerTrait::::new(13_u32, false); let b = IntegerTrait::::new(5_u32, false); let (q, r) = a.div_rem(b); - assert(q.mag == 2_u32 & r.mag == 3_u32, '13 // 5 = 2 r 3'); + assert((q.mag == 2_u32) & (r.mag == 3_u32), '13 // 5 = 2 r 3'); assert(q.sign == false & r.sign == false, '13 // 5 -> positive'); // Test division and remainder of negative integers let a = IntegerTrait::::new(13_u32, true); let b = IntegerTrait::::new(5_u32, true); let (q, r) = a.div_rem(b); - assert(q.mag == 2_u32 & r.mag == 3_u32, '-13 // -5 = 2 r -3'); + assert((q.mag == 2_u32) & (r.mag == 3_u32), '-13 // -5 = 2 r -3'); assert(q.sign == false & r.sign == true, '-13 // -5 -> positive'); // Test division and remainder of positive and negative integers let a = IntegerTrait::::new(13_u32, false); let b = IntegerTrait::::new(5_u32, true); let (q, r) = a.div_rem(b); - assert(q.mag == 3_u32 & r.mag == 2_u32, '13 // -5 = -3 r -2'); + assert((q.mag == 3_u32) & (r.mag == 2_u32), '13 // -5 = -3 r -2'); assert(q.sign == true & r.sign == true, '13 // -5 -> negative'); // Test division with a = zero let a = IntegerTrait::::new(0_u32, false); let b = IntegerTrait::::new(10_u32, false); let (q, r) = a.div_rem(b); - assert(q.mag == 0_u32 & r.mag == 0_u32, '0 // 10 = 0 r 0'); + assert((q.mag == 0_u32) & (r.mag == 0_u32), '0 // 10 = 0 r 0'); assert(q.sign == false & r.sign == false, '0 // 10 -> positive'); // Test division and remainder with a negative dividend and positive divisor let a = IntegerTrait::::new(13_u32, true); let b = IntegerTrait::::new(5_u32, false); let (q, r) = a.div_rem(b); - assert(q.mag == 3_u32 & r.mag == 2_u32, '-13 // 5 = -3 r 2'); + assert((q.mag == 3_u32) & (r.mag == 2_u32), '-13 // 5 = -3 r 2'); assert(q.sign == true & r.sign == false, '-13 // 5 -> negative'); } diff --git a/src/tests/operators/linalg/matmul_test.cairo b/src/tests/operators/linalg/matmul_test.cairo index 52b8b6d50..9aca7edbd 100644 --- a/src/tests/operators/linalg/matmul_test.cairo +++ b/src/tests/operators/linalg/matmul_test.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use array::SpanTrait; use traits::Into; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::TensorTrait; use orion::tests::operators::tensor::helpers::helpers_i32::{ i32_tensor_1x3_helper, i32_tensor_2x2_helper, i32_tensor_3x3_helper diff --git a/src/tests/operators/math/abs/abs_fp_test.cairo b/src/tests/operators/math/abs/abs_fp_test.cairo index 8f5b7804d..989731ba7 100644 --- a/src/tests/operators/math/abs/abs_fp_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test.cairo @@ -2,10 +2,10 @@ use array::SpanTrait; use array::ArrayTrait; use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; #[test] @@ -28,9 +28,7 @@ fn tensor_abs_fp() { let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new( - sizes.span(), arr.span(), Option::Some(extra) - ); + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); let result = tensor.abs(); assert(*result.data.at(0) == FixedTrait::new(0, false), 'result[0] = 0'); diff --git a/src/tests/operators/math/abs/abs_i32_test.cairo b/src/tests/operators/math/abs/abs_i32_test.cairo index 11e72d72a..0e9cb4061 100644 --- a/src/tests/operators/math/abs/abs_i32_test.cairo +++ b/src/tests/operators/math/abs/abs_i32_test.cairo @@ -2,7 +2,7 @@ use array::SpanTrait; use array::ArrayTrait; use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; diff --git a/src/tests/operators/math/abs/abs_u32_test.cairo b/src/tests/operators/math/abs/abs_u32_test.cairo index cbfa65ccd..29c037512 100644 --- a/src/tests/operators/math/abs/abs_u32_test.cairo +++ b/src/tests/operators/math/abs/abs_u32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::ArrayTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo index 2d9a7fc26..0b56858c2 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo @@ -3,8 +3,8 @@ mod tensor1D_argmax_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_16x16; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -116,8 +116,8 @@ mod tensor1D_argmax_fp { mod tensor2x2_argmax_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_16x16; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_fp::fp16x16_helpers::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper @@ -207,8 +207,8 @@ mod tensor2x2_argmax_fp { mod tensor2x2x2_argmax_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_16x16; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_fp::fp16x16_helpers::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo index 775da8afb..56d64bd92 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo @@ -3,8 +3,8 @@ mod tensor1D_argmax_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_8x23; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -116,8 +116,8 @@ mod tensor1D_argmax_fp { mod tensor2x2_argmax_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_8x23; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_fp::fp8x23_helpers::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper @@ -207,8 +207,8 @@ mod tensor2x2_argmax_fp { mod tensor2x2x2_argmax_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_8x23; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_fp::fp8x23_helpers::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper diff --git a/src/tests/operators/math/argmax/argmax_i32_test.cairo b/src/tests/operators/math/argmax/argmax_i32_test.cairo index 4161bcb6a..82fc5c120 100644 --- a/src/tests/operators/math/argmax/argmax_i32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_i32_test.cairo @@ -3,7 +3,7 @@ mod tensor1D_argmax_i32 { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; - use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; #[test] @@ -114,7 +114,7 @@ mod tensor1D_argmax_i32 { mod tensor2x2_argmax_i32 { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; - use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; @@ -201,7 +201,7 @@ mod tensor2x2_argmax_i32 { mod tensor2x2x2_argmax_i32 { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; - use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; diff --git a/src/tests/operators/math/argmax/argmax_u32_test.cairo b/src/tests/operators/math/argmax/argmax_u32_test.cairo index 83821921c..9272b3066 100644 --- a/src/tests/operators/math/argmax/argmax_u32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_u32_test.cairo @@ -2,7 +2,7 @@ #[cfg(test)] mod tensor1D_argmax_u32 { use array::{ArrayTrait,SpanTrait}; - use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; #[test] @@ -99,7 +99,7 @@ mod tensor1D_argmax_u32 { #[cfg(test)] mod tensor2x2_argmax_u32 { use array::{ArrayTrait,SpanTrait}; - use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; @@ -185,7 +185,7 @@ mod tensor2x2_argmax_u32 { #[cfg(test)] mod tensor2x2x2_argmax_u32 { use array::{ArrayTrait,SpanTrait}; - use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo index 49eb88e2f..52adfacf2 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo @@ -3,8 +3,8 @@ mod tensor1D_argmin_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_16x16; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; #[test] @@ -124,8 +124,8 @@ mod tensor1D_argmin_fp { mod tensor2x2_argmin_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_16x16; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_fp::fp16x16_helpers::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper @@ -226,8 +226,8 @@ mod tensor2x2_argmin_fp { mod tensor2x2x2_argmin_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_16x16; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_fp::fp16x16_helpers::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo index fb15806d6..2eebd04c5 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo @@ -3,8 +3,8 @@ mod tensor1D_argmin_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_8x23; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; #[test] @@ -124,8 +124,8 @@ mod tensor1D_argmin_fp { mod tensor2x2_argmin_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_8x23; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_fp::fp8x23_helpers::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper @@ -226,8 +226,8 @@ mod tensor2x2_argmin_fp { mod tensor2x2x2_argmin_fp { use array::{ArrayTrait,SpanTrait}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; - use orion::numbers::fixed_point::implementations::impl_8x23; - use orion::operators::tensor::implementations::impl_tensor_fp; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_fp::fp8x23_helpers::{ fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper diff --git a/src/tests/operators/math/argmin/argmin_i32_test.cairo b/src/tests/operators/math/argmin/argmin_i32_test.cairo index e678c2321..5e6786656 100644 --- a/src/tests/operators/math/argmin/argmin_i32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_i32_test.cairo @@ -3,7 +3,7 @@ mod tensor1D_argmin_i32 { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; - use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; #[test] @@ -123,7 +123,7 @@ mod tensor1D_argmin_i32 { mod tensor2x2_argmin_i32 { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; - use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; @@ -222,7 +222,7 @@ mod tensor2x2_argmin_i32 { mod tensor2x2x2_argmin_i32 { use array::{ArrayTrait,SpanTrait}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; - use orion::operators::tensor::implementations::impl_tensor_i32; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_1x3_helper,i32_tensor_2x2_helper, i32_tensor_2x2x2_helper}; diff --git a/src/tests/operators/math/argmin/argmin_u32_test.cairo b/src/tests/operators/math/argmin/argmin_u32_test.cairo index 5e3341ff4..c7fac43d0 100644 --- a/src/tests/operators/math/argmin/argmin_u32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_u32_test.cairo @@ -2,7 +2,7 @@ #[cfg(test)] mod tensor1D_argmin_u32 { use array::{ArrayTrait,SpanTrait}; - use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; #[test] @@ -108,7 +108,7 @@ mod tensor1D_argmin_u32 { #[cfg(test)] mod tensor2x2_argmin_u32 { use array::{ArrayTrait,SpanTrait}; - use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; @@ -206,7 +206,7 @@ mod tensor2x2_argmin_u32 { #[cfg(test)] mod tensor2x2x2_argmin_u32 { use array::{ArrayTrait,SpanTrait}; - use orion::operators::tensor::implementations::impl_tensor_u32; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::operators::tensor::helpers::helpers_u32::{u32_tensor_1x3_helper,u32_tensor_2x2_helper, u32_tensor_2x2x2_helper}; diff --git a/src/tests/operators/math/ceil/ceil_fp_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test.cairo index ceffe77f0..8abd060ac 100644 --- a/src/tests/operators/math/ceil/ceil_fp_test.cairo +++ b/src/tests/operators/math/ceil/ceil_fp_test.cairo @@ -1,10 +1,10 @@ use array::SpanTrait; use array::ArrayTrait; use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; #[test] @@ -22,15 +22,17 @@ fn tensor_ceil_fp() { let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new( - sizes.span(), arr.span(), Option::Some(extra) - ); + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); let result = tensor.ceil(); assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 8388608'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false),'result[2] = 100663296'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -92274688'); // -11 + assert( + *result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 100663296' + ); // 12 + assert( + *result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -92274688' + ); // -11 assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/math/ceil/ceil_i32_test.cairo b/src/tests/operators/math/ceil/ceil_i32_test.cairo index e3dad68d7..43a8dadd7 100644 --- a/src/tests/operators/math/ceil/ceil_i32_test.cairo +++ b/src/tests/operators/math/ceil/ceil_i32_test.cairo @@ -2,7 +2,7 @@ use array::SpanTrait; use array::ArrayTrait; use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; diff --git a/src/tests/operators/math/ceil/ceil_u32_test.cairo b/src/tests/operators/math/ceil/ceil_u32_test.cairo index 7841802e0..2c4a5d8f2 100644 --- a/src/tests/operators/math/ceil/ceil_u32_test.cairo +++ b/src/tests/operators/math/ceil/ceil_u32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::ArrayTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; diff --git a/src/tests/operators/math/equal/equal_fp_test.cairo b/src/tests/operators/math/equal/equal_fp_test.cairo index 9d50ca91f..89633d3b7 100644 --- a/src/tests/operators/math/equal/equal_fp_test.cairo +++ b/src/tests/operators/math/equal/equal_fp_test.cairo @@ -1,9 +1,9 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/math/equal/equal_i32_test.cairo b/src/tests/operators/math/equal/equal_i32_test.cairo index 15dd13692..c1ad205a3 100644 --- a/src/tests/operators/math/equal/equal_i32_test.cairo +++ b/src/tests/operators/math/equal/equal_i32_test.cairo @@ -1,7 +1,7 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; diff --git a/src/tests/operators/math/equal/equal_u32_test.cairo b/src/tests/operators/math/equal/equal_u32_test.cairo index 8f4dae6b9..3b362c11d 100644 --- a/src/tests/operators/math/equal/equal_u32_test.cairo +++ b/src/tests/operators/math/equal/equal_u32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; #[test] diff --git a/src/tests/operators/math/exp_test.cairo b/src/tests/operators/math/exp_test.cairo index b058631dd..2a553ebef 100644 --- a/src/tests/operators/math/exp_test.cairo +++ b/src/tests/operators/math/exp_test.cairo @@ -1,10 +1,10 @@ use array::SpanTrait; use traits::Into; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, }; use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; #[test] #[available_gas(20000000)] diff --git a/src/tests/operators/math/greater/greater_fp_test.cairo b/src/tests/operators/math/greater/greater_fp_test.cairo index 031344b7e..c13564e54 100644 --- a/src/tests/operators/math/greater/greater_fp_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test.cairo @@ -1,9 +1,9 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/math/greater/greater_i32_test.cairo b/src/tests/operators/math/greater/greater_i32_test.cairo index 51eaa24fc..84d9f946a 100644 --- a/src/tests/operators/math/greater/greater_i32_test.cairo +++ b/src/tests/operators/math/greater/greater_i32_test.cairo @@ -1,7 +1,7 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; diff --git a/src/tests/operators/math/greater/greater_u32_test.cairo b/src/tests/operators/math/greater/greater_u32_test.cairo index e8c6a9cbe..0bc034518 100644 --- a/src/tests/operators/math/greater/greater_u32_test.cairo +++ b/src/tests/operators/math/greater/greater_u32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; #[test] diff --git a/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo index 1e0d3a2aa..ac1784173 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo @@ -1,9 +1,8 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp;use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] diff --git a/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo index d2cb7825a..6d1c7b4cd 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; diff --git a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo index b189a197f..339f503df 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; #[test] diff --git a/src/tests/operators/math/less/less_fp_test.cairo b/src/tests/operators/math/less/less_fp_test.cairo index 6c4940a15..a92f04346 100644 --- a/src/tests/operators/math/less/less_fp_test.cairo +++ b/src/tests/operators/math/less/less_fp_test.cairo @@ -1,9 +1,8 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp;use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/math/less/less_i32_test.cairo b/src/tests/operators/math/less/less_i32_test.cairo index 567614d02..7f04b2b8e 100644 --- a/src/tests/operators/math/less/less_i32_test.cairo +++ b/src/tests/operators/math/less/less_i32_test.cairo @@ -1,7 +1,7 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; diff --git a/src/tests/operators/math/less/less_u32_test.cairo b/src/tests/operators/math/less/less_u32_test.cairo index 865755702..b173cc045 100644 --- a/src/tests/operators/math/less/less_u32_test.cairo +++ b/src/tests/operators/math/less/less_u32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; #[test] diff --git a/src/tests/operators/math/less_equal/less_equal_fp_test.cairo b/src/tests/operators/math/less_equal/less_equal_fp_test.cairo index 314096356..c821ca3e5 100644 --- a/src/tests/operators/math/less_equal/less_equal_fp_test.cairo +++ b/src/tests/operators/math/less_equal/less_equal_fp_test.cairo @@ -1,9 +1,8 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp;use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/math/less_equal/less_equal_i32_test.cairo b/src/tests/operators/math/less_equal/less_equal_i32_test.cairo index cede4aa75..e85236e3c 100644 --- a/src/tests/operators/math/less_equal/less_equal_i32_test.cairo +++ b/src/tests/operators/math/less_equal/less_equal_i32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; diff --git a/src/tests/operators/math/less_equal/less_equal_u32_test.cairo b/src/tests/operators/math/less_equal/less_equal_u32_test.cairo index 98d6e0fcb..b2c5f5073 100644 --- a/src/tests/operators/math/less_equal/less_equal_u32_test.cairo +++ b/src/tests/operators/math/less_equal/less_equal_u32_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; #[test] diff --git a/src/tests/operators/math/ln_test.cairo b/src/tests/operators/math/ln_test.cairo index a433c6909..5c76d27a4 100644 --- a/src/tests/operators/math/ln_test.cairo +++ b/src/tests/operators/math/ln_test.cairo @@ -2,10 +2,10 @@ use array::SpanTrait; use traits::Into; use array::ArrayTrait; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; diff --git a/src/tests/operators/math/max_test.cairo b/src/tests/operators/math/max_test.cairo index f25b085ed..40d491cd7 100644 --- a/src/tests/operators/math/max_test.cairo +++ b/src/tests/operators/math/max_test.cairo @@ -1,4 +1,4 @@ -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::TensorTrait; use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2x2_helper; diff --git a/src/tests/operators/math/min_test.cairo b/src/tests/operators/math/min_test.cairo index 6790676e2..2f1d35a85 100644 --- a/src/tests/operators/math/min_test.cairo +++ b/src/tests/operators/math/min_test.cairo @@ -1,4 +1,4 @@ -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::TensorTrait; use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2x2_helper; diff --git a/src/tests/operators/math/reduce_sum_test.cairo b/src/tests/operators/math/reduce_sum_test.cairo index d74059fa8..c18d963ce 100644 --- a/src/tests/operators/math/reduce_sum_test.cairo +++ b/src/tests/operators/math/reduce_sum_test.cairo @@ -1,6 +1,6 @@ use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::TensorTrait; use orion::tests::operators::tensor::helpers::helpers_i32::{i32_tensor_2x2x2_helper, i32_tensor_1x3_helper}; diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo index 138e31129..f7ddef031 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo @@ -3,13 +3,13 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::{NNTrait}; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE}; #[test] #[available_gas(2000000)] @@ -42,7 +42,7 @@ fn leaky_relu_i32_test() { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); let data_0 = *result.data.at(0); - assert(data_0.mag == impl_8x23::ONE, 'result[0] == 8388608'); // 1 + assert(data_0.mag == ONE, 'result[0] == 8388608'); // 1 assert(data_0.sign == false, 'result[0].sign == false'); let data_3 = *result.data.at(3); diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo index 8245f2a90..d95b46563 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo @@ -4,12 +4,12 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/nn/functional/linear/linear_test.cairo b/src/tests/operators/nn/functional/linear/linear_test.cairo index 7b6fc56d8..a14cc4d7c 100644 --- a/src/tests/operators/nn/functional/linear/linear_test.cairo +++ b/src/tests/operators/nn/functional/linear/linear_test.cairo @@ -2,10 +2,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; #[test] @@ -47,16 +47,21 @@ fn linear_test() { // TEST UNQUANTIZED let result = NNTrait::linear(inputs, weights, bias, false).data; assert( - *result.at(0_usize).mag == 5541_u32 & *result.at(0_usize).sign == false, 'result[0] = 5541' + (*result.at(0_usize).mag == 5541_u32) & (*result.at(0_usize).sign == false), + 'result[0] = 5541' ); assert( - *result.at(1_usize).mag == 260_u32 & *result.at(1_usize).sign == true, 'result[1] = -260' + (*result.at(1_usize).mag == 260_u32) & (*result.at(1_usize).sign == true), + 'result[1] = -260' ); // TEST QUANTIZED let result = NNTrait::linear(inputs, weights, bias, true).data; assert( - *result.at(0_usize).mag == 127_u32 & *result.at(0_usize).sign == false, 'result[0] = 127' + (*result.at(0_usize).mag == 127_u32) & (*result.at(0_usize).sign == false), + 'result[0] = 127' + ); + assert( + (*result.at(1_usize).mag == 6_u32) & (*result.at(1_usize).sign == true), 'result[1] = -6' ); - assert(*result.at(1_usize).mag == 6_u32 & *result.at(1_usize).sign == true, 'result[1] = -6'); } diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo index 4b566a42a..60e940a0a 100644 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo @@ -4,10 +4,10 @@ use traits::Into; use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use debug::PrintTrait; use debug::print_felt252; diff --git a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo index fc1909e26..5daba51d2 100644 --- a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo @@ -2,10 +2,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo index 4b769be56..c95d803e1 100644 --- a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo @@ -2,10 +2,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; #[test] #[available_gas(2000000)] diff --git a/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo b/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo index 67cfa7cc2..9cd5ac464 100644 --- a/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo +++ b/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo @@ -4,10 +4,10 @@ use array::SpanTrait; use core::Into; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; diff --git a/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo b/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo index 47221a8cb..47c3c9119 100644 --- a/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo +++ b/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo @@ -3,10 +3,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::numbers::signed_integer::integer_trait::IntegerTrait; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; #[test] diff --git a/src/tests/operators/nn/functional/softmax/softmax_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_test.cairo index e98ff4a03..6b7b0c3f2 100644 --- a/src/tests/operators/nn/functional/softmax/softmax_test.cairo +++ b/src/tests/operators/nn/functional/softmax/softmax_test.cairo @@ -4,10 +4,10 @@ use traits::Into; use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use debug::print_felt252; diff --git a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo index 50797d98c..372e094ec 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo @@ -3,10 +3,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use orion::numbers::fixed_point::core::FixedImpl; diff --git a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo index e202dcb34..a93b6ca1b 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo @@ -3,13 +3,13 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::numbers::signed_integer::integer_trait::IntegerTrait; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; use orion::numbers::fixed_point::core::FixedTrait; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; use orion::numbers::fixed_point::core::FixedImpl; #[test] diff --git a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo index 7de4417c2..97dca3688 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo @@ -3,10 +3,10 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32; +use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use orion::numbers::fixed_point::core::FixedImpl; #[test] diff --git a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo index ee729d56a..18423a1b5 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo @@ -4,13 +4,13 @@ use array::ArrayTrait; use array::SpanTrait; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32; +use orion::operators::nn::implementations::impl_nn_u32::NN_u32; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; use orion::numbers::fixed_point::core::FixedImpl; #[test] diff --git a/src/tests/operators/tensor/helpers/helpers_fp/fp16x16_helpers.cairo b/src/tests/operators/tensor/helpers/helpers_fp/fp16x16_helpers.cairo index b473de728..8debc007f 100644 --- a/src/tests/operators/tensor/helpers/helpers_fp/fp16x16_helpers.cairo +++ b/src/tests/operators/tensor/helpers/helpers_fp/fp16x16_helpers.cairo @@ -1,8 +1,8 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_16x16; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; // 1D diff --git a/src/tests/operators/tensor/helpers/helpers_fp/fp8x23_helpers.cairo b/src/tests/operators/tensor/helpers/helpers_fp/fp8x23_helpers.cairo index 03108ce41..e6e515d61 100644 --- a/src/tests/operators/tensor/helpers/helpers_fp/fp8x23_helpers.cairo +++ b/src/tests/operators/tensor/helpers/helpers_fp/fp8x23_helpers.cairo @@ -1,9 +1,8 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_8x23; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp;use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; // 1D fn fp_tensor_1x3_helper() -> Tensor { diff --git a/src/tests/operators/tensor/helpers/helpers_i32.cairo b/src/tests/operators/tensor/helpers/helpers_i32.cairo index 9c3fb3d76..3a8dce18b 100644 --- a/src/tests/operators/tensor/helpers/helpers_i32.cairo +++ b/src/tests/operators/tensor/helpers/helpers_i32.cairo @@ -3,7 +3,7 @@ use array::SpanTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; // 1D diff --git a/src/tests/operators/tensor/helpers/helpers_u32.cairo b/src/tests/operators/tensor/helpers/helpers_u32.cairo index b02ed4a15..6cfb79645 100644 --- a/src/tests/operators/tensor/helpers/helpers_u32.cairo +++ b/src/tests/operators/tensor/helpers/helpers_u32.cairo @@ -1,6 +1,6 @@ use array::ArrayTrait; use array::SpanTrait; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; // 1D diff --git a/src/tests/operators/tensor/tensor_test.cairo b/src/tests/operators/tensor/tensor_test.cairo index 737d7076b..d642185e2 100644 --- a/src/tests/operators/tensor/tensor_test.cairo +++ b/src/tests/operators/tensor/tensor_test.cairo @@ -2,7 +2,9 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::{ + Tensor_i32, i32TensorAdd, i32TensorSub, i32TensorMul, i32TensorDiv +}; use orion::operators::tensor::core::{TensorTrait, ExtraParams, ravel_index, unravel_index}; use orion::tests::operators::tensor::helpers::helpers_i32::{ i32_tensor_2x2_helper, i32_tensor_3x2_helper, i32_tensor_2x3_helper, i32_tensor_2x2x2_helper, diff --git a/src/tests/performance/quantization_test.cairo b/src/tests/performance/quantization_test.cairo index be8830ab3..584dfd444 100644 --- a/src/tests/performance/quantization_test.cairo +++ b/src/tests/performance/quantization_test.cairo @@ -3,12 +3,12 @@ use array::SpanTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::operators::tensor::implementations::impl_tensor_i32; -use orion::operators::tensor::implementations::impl_tensor_fp; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::performance::core::PerfomanceTrait; -use orion::performance::implementations::impl_performance_i32; +use orion::performance::implementations::impl_performance_i32::Performance_i32; #[test] diff --git a/src/utils.cairo b/src/utils.cairo index d65192878..c020a4f9d 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -4,7 +4,7 @@ use array::ArrayTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE}; // Fake macro to compute gas left // TODO: Remove when automatically handled by compiler. @@ -29,11 +29,11 @@ fn u32_max(a: u32, b: u32) -> u32 { } fn fp8x23_to_i32(x: FixedType) -> i32 { - let unscaled_mag = x.mag / impl_8x23::ONE; + let unscaled_mag = x.mag / ONE; return IntegerTrait::new(unscaled_mag.try_into().unwrap(), x.sign); } fn fp8x23_to_u32(x: FixedType) -> u32 { - let unscaled_mag = x.mag / impl_8x23::ONE; + let unscaled_mag = x.mag / ONE; return unscaled_mag.try_into().unwrap(); } From f6138e5791db264043f41d574f9c2505ee5bd77c Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 19:22:41 +0300 Subject: [PATCH 017/126] fix test_div_rem --- src/tests/numbers/signed_integer_test.cairo | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tests/numbers/signed_integer_test.cairo b/src/tests/numbers/signed_integer_test.cairo index 4c92cb2f7..73a0216c0 100644 --- a/src/tests/numbers/signed_integer_test.cairo +++ b/src/tests/numbers/signed_integer_test.cairo @@ -191,34 +191,34 @@ fn test_div_rem() { let a = IntegerTrait::::new(13_u32, false); let b = IntegerTrait::::new(5_u32, false); let (q, r) = a.div_rem(b); - assert((q.mag == 2_u32) & (r.mag == 3_u32), '13 // 5 = 2 r 3'); - assert(q.sign == false & r.sign == false, '13 // 5 -> positive'); + assert(q.mag == 2_u32 && r.mag == 3_u32, '13 // 5 = 2 r 3'); + assert((q.sign == false) & (r.sign == false), '13 // 5 -> positive'); // Test division and remainder of negative integers let a = IntegerTrait::::new(13_u32, true); let b = IntegerTrait::::new(5_u32, true); let (q, r) = a.div_rem(b); - assert((q.mag == 2_u32) & (r.mag == 3_u32), '-13 // -5 = 2 r -3'); - assert(q.sign == false & r.sign == true, '-13 // -5 -> positive'); + assert(q.mag == 2_u32 && r.mag == 3_u32, '-13 // -5 = 2 r -3'); + assert(q.sign == false && r.sign == true, '-13 // -5 -> positive'); // Test division and remainder of positive and negative integers let a = IntegerTrait::::new(13_u32, false); let b = IntegerTrait::::new(5_u32, true); let (q, r) = a.div_rem(b); - assert((q.mag == 3_u32) & (r.mag == 2_u32), '13 // -5 = -3 r -2'); - assert(q.sign == true & r.sign == true, '13 // -5 -> negative'); + assert(q.mag == 3_u32 && r.mag == 2_u32, '13 // -5 = -3 r -2'); + assert(q.sign == true && r.sign == true, '13 // -5 -> negative'); // Test division with a = zero let a = IntegerTrait::::new(0_u32, false); let b = IntegerTrait::::new(10_u32, false); let (q, r) = a.div_rem(b); - assert((q.mag == 0_u32) & (r.mag == 0_u32), '0 // 10 = 0 r 0'); - assert(q.sign == false & r.sign == false, '0 // 10 -> positive'); + assert(q.mag == 0_u32 && r.mag == 0_u32, '0 // 10 = 0 r 0'); + assert(q.sign == false && r.sign == false, '0 // 10 -> positive'); // Test division and remainder with a negative dividend and positive divisor let a = IntegerTrait::::new(13_u32, true); let b = IntegerTrait::::new(5_u32, false); let (q, r) = a.div_rem(b); - assert((q.mag == 3_u32) & (r.mag == 2_u32), '-13 // 5 = -3 r 2'); - assert(q.sign == true & r.sign == false, '-13 // 5 -> negative'); + assert(q.mag == 3_u32 && r.mag == 2_u32, '-13 // 5 = -3 r 2'); + assert(q.sign == true && r.sign == false, '-13 // 5 -> negative'); } From 23655a48743334746a1af5ba6933ecd120bcbb97 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 20:22:42 +0300 Subject: [PATCH 018/126] refactor bitwise ops --- src/numbers/fixed_point/math/math_16x16.cairo | 12 ++++++------ src/numbers/fixed_point/math/math_8x23.cairo | 12 ++++++------ src/numbers/signed_integer/i128.cairo | 8 ++++---- src/numbers/signed_integer/i16.cairo | 8 ++++---- src/numbers/signed_integer/i32.cairo | 8 ++++---- src/numbers/signed_integer/i64.cairo | 8 ++++---- src/numbers/signed_integer/i8.cairo | 8 ++++---- src/operators/tensor/helpers.cairo | 4 ++-- src/operators/tensor/linalg/matmul/helpers.cairo | 4 ++-- .../tensor/linalg/matmul/matmul_fp/fp16x16.cairo | 4 ++-- .../tensor/linalg/matmul/matmul_fp/fp8x23.cairo | 4 ++-- src/operators/tensor/linalg/matmul/matmul_i32.cairo | 4 ++-- src/operators/tensor/linalg/matmul/matmul_u32.cairo | 4 ++-- src/operators/tensor/math/argmax/helpers.cairo | 4 ++-- src/operators/tensor/math/argmin/helpers.cairo | 4 ++-- .../operators/nn/functional/linear/linear_test.cairo | 8 ++++---- 16 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/numbers/fixed_point/math/math_16x16.cairo b/src/numbers/fixed_point/math/math_16x16.cairo index 02c451481..9b8354928 100644 --- a/src/numbers/fixed_point/math/math_16x16.cairo +++ b/src/numbers/fixed_point/math/math_16x16.cairo @@ -74,7 +74,7 @@ fn div(a: FixedType, b: FixedType) -> FixedType { /// /// * A boolean value that indicates whether the input fixed point numbers are equal. fn eq(a: FixedType, b: FixedType) -> bool { - return (a.mag == b.mag) & (a.sign == b.sign); + return a.mag == b.mag && a.sign == b.sign; } /// Cf: FixedTrait::exp docstring @@ -144,7 +144,7 @@ fn ge(a: FixedType, b: FixedType) -> bool { if (a.sign != b.sign) { return !a.sign; } else { - return (a.mag == b.mag) | ((a.mag > b.mag) ^ a.sign); + return a.mag == b.mag || (a.mag > b.mag) ^ a.sign; } } @@ -162,7 +162,7 @@ fn gt(a: FixedType, b: FixedType) -> bool { if (a.sign != b.sign) { return !a.sign; } else { - return (a.mag != b.mag) & ((a.mag > b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag > b.mag) ^ a.sign; } } @@ -180,7 +180,7 @@ fn le(a: FixedType, b: FixedType) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag == b.mag) | ((a.mag < b.mag) ^ a.sign); + return a.mag == b.mag || (a.mag < b.mag) ^ a.sign; } } @@ -247,7 +247,7 @@ fn lt(a: FixedType, b: FixedType) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag != b.mag) & ((a.mag < b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag < b.mag) ^ a.sign; } } @@ -286,7 +286,7 @@ fn mul(a: FixedType, b: FixedType) -> FixedType { /// /// * A boolean value that indicates whether the first fixed point number is not equal to the second fixed point number. fn ne(a: FixedType, b: FixedType) -> bool { - return (a.mag != b.mag) | (a.sign != b.sign); + return a.mag != b.mag || a.sign != b.sign; } /// Negates a fixed point number. diff --git a/src/numbers/fixed_point/math/math_8x23.cairo b/src/numbers/fixed_point/math/math_8x23.cairo index 08e8c4b64..658d0c86b 100644 --- a/src/numbers/fixed_point/math/math_8x23.cairo +++ b/src/numbers/fixed_point/math/math_8x23.cairo @@ -74,7 +74,7 @@ fn div(a: FixedType, b: FixedType) -> FixedType { /// /// * A boolean value that indicates whether the input fixed point numbers are equal. fn eq(a: FixedType, b: FixedType) -> bool { - return (a.mag == b.mag) & (a.sign == b.sign); + return a.mag == b.mag && a.sign == b.sign; } /// Cf: FixedTrait::exp docstring @@ -146,7 +146,7 @@ fn ge(a: FixedType, b: FixedType) -> bool { if (a.sign != b.sign) { return !a.sign; } else { - return (a.mag == b.mag) | ((a.mag > b.mag) ^ a.sign); + return a.mag == b.mag || (a.mag > b.mag) ^ a.sign; } } @@ -164,7 +164,7 @@ fn gt(a: FixedType, b: FixedType) -> bool { if (a.sign != b.sign) { return !a.sign; } else { - return (a.mag != b.mag) & ((a.mag > b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag > b.mag) ^ a.sign; } } @@ -182,7 +182,7 @@ fn le(a: FixedType, b: FixedType) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag == b.mag) | ((a.mag < b.mag) ^ a.sign); + return a.mag == b.mag || (a.mag < b.mag) ^ a.sign; } } @@ -249,7 +249,7 @@ fn lt(a: FixedType, b: FixedType) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag != b.mag) & ((a.mag < b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag < b.mag) ^ a.sign; } } @@ -288,7 +288,7 @@ fn mul(a: FixedType, b: FixedType) -> FixedType { /// /// * A boolean value that indicates whether the first fixed point number is not equal to the second fixed point number. fn ne(a: FixedType, b: FixedType) -> bool { - return (a.mag != b.mag) | (a.sign != b.sign); + return a.mag != b.mag || a.sign != b.sign; } /// Negates a fixed point number. diff --git a/src/numbers/signed_integer/i128.cairo b/src/numbers/signed_integer/i128.cairo index 3319b6635..c8f7e2f47 100644 --- a/src/numbers/signed_integer/i128.cairo +++ b/src/numbers/signed_integer/i128.cairo @@ -337,7 +337,7 @@ fn i128_div_rem(a: i128, b: i128) -> (i128, i128) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i128_eq(a: i128, b: i128) -> bool { // Check if the two integers have the same sign and the same absolute value. - if (a.sign == b.sign) & (a.mag == b.mag) { + if a.sign == b.sign && a.mag == b.mag { return true; } @@ -388,7 +388,7 @@ fn i128_lt(a: i128, b: i128) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag != b.mag) & ((a.mag < b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag < b.mag) ^ a.sign; } } @@ -399,7 +399,7 @@ fn i128_lt(a: i128, b: i128) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i128_le(a: i128, b: i128) -> bool { - if ((a == b) | (i128_lt(a, b) == true)) { + if (a == b || i128_lt(a, b) == true) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i128_le(a: i128, b: i128) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i128_ge(a: i128, b: i128) -> bool { - if ((a == b) | (i128_gt(a, b) == true)) { + if (a == b || i128_gt(a, b) == true) { return true; } else { return false; diff --git a/src/numbers/signed_integer/i16.cairo b/src/numbers/signed_integer/i16.cairo index 86d8157ad..c38881009 100644 --- a/src/numbers/signed_integer/i16.cairo +++ b/src/numbers/signed_integer/i16.cairo @@ -337,7 +337,7 @@ fn i16_div_rem(a: i16, b: i16) -> (i16, i16) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i16_eq(a: i16, b: i16) -> bool { // Check if the two integers have the same sign and the same absolute value. - if (a.sign == b.sign) & (a.mag == b.mag) { + if a.sign == b.sign && a.mag == b.mag { return true; } @@ -388,7 +388,7 @@ fn i16_lt(a: i16, b: i16) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag != b.mag) & ((a.mag < b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag < b.mag) ^ a.sign; } } @@ -399,7 +399,7 @@ fn i16_lt(a: i16, b: i16) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i16_le(a: i16, b: i16) -> bool { - if ((a == b) | (i16_lt(a, b) == true)) { + if (a == b || i16_lt(a, b) == true) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i16_le(a: i16, b: i16) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i16_ge(a: i16, b: i16) -> bool { - if ((a == b) | i16_gt(a, b) == true) { + if (a == b || i16_gt(a, b) == true) { return true; } else { return false; diff --git a/src/numbers/signed_integer/i32.cairo b/src/numbers/signed_integer/i32.cairo index f2beef3ce..01d55f151 100644 --- a/src/numbers/signed_integer/i32.cairo +++ b/src/numbers/signed_integer/i32.cairo @@ -337,7 +337,7 @@ fn i32_div_rem(a: i32, b: i32) -> (i32, i32) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i32_eq(a: i32, b: i32) -> bool { // Check if the two integers have the same sign and the same absolute value. - if (a.sign == b.sign) & (a.mag == b.mag) { + if a.sign == b.sign && a.mag == b.mag { return true; } @@ -388,7 +388,7 @@ fn i32_lt(a: i32, b: i32) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag != b.mag) & ((a.mag < b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag < b.mag) ^ a.sign; } } @@ -399,7 +399,7 @@ fn i32_lt(a: i32, b: i32) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i32_le(a: i32, b: i32) -> bool { - if ((a == b) | (i32_lt(a, b) == true)) { + if (a == b || i32_lt(a, b) == true) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i32_le(a: i32, b: i32) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i32_ge(a: i32, b: i32) -> bool { - if ((a == b )| (i32_gt(a, b) == true)) { + if (a == b || i32_gt(a, b) == true) { return true; } else { return false; diff --git a/src/numbers/signed_integer/i64.cairo b/src/numbers/signed_integer/i64.cairo index 34fdf1fdd..efd9ea9c4 100644 --- a/src/numbers/signed_integer/i64.cairo +++ b/src/numbers/signed_integer/i64.cairo @@ -337,7 +337,7 @@ fn i64_div_rem(a: i64, b: i64) -> (i64, i64) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i64_eq(a: i64, b: i64) -> bool { // Check if the two integers have the same sign and the same absolute value. - if (a.sign == b.sign )& (a.mag == b.mag) { + if a.sign == b.sign && a.mag == b.mag { return true; } @@ -388,7 +388,7 @@ fn i64_lt(a: i64, b: i64) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag != b.mag) & ((a.mag < b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag < b.mag) ^ a.sign; } } @@ -399,7 +399,7 @@ fn i64_lt(a: i64, b: i64) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i64_le(a: i64, b: i64) -> bool { - if ((a == b) | (i64_lt(a, b) == true)) { + if (a == b || i64_lt(a, b) == true) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i64_le(a: i64, b: i64) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i64_ge(a: i64, b: i64) -> bool { - if ((a == b) | (i64_gt(a, b) == true)) { + if (a == b || i64_gt(a, b) == true) { return true; } else { return false; diff --git a/src/numbers/signed_integer/i8.cairo b/src/numbers/signed_integer/i8.cairo index 79f114eb2..9dfcdeb54 100644 --- a/src/numbers/signed_integer/i8.cairo +++ b/src/numbers/signed_integer/i8.cairo @@ -337,7 +337,7 @@ fn i8_div_rem(a: i8, b: i8) -> (i8, i8) { // * `bool` - `true` if the two integers are equal, `false` otherwise. fn i8_eq(a: i8, b: i8) -> bool { // Check if the two integers have the same sign and the same absolute value. - if (a.sign == b.sign) & (a.mag == b.mag) { + if a.sign == b.sign && a.mag == b.mag { return true; } @@ -388,7 +388,7 @@ fn i8_lt(a: i8, b: i8) -> bool { if (a.sign != b.sign) { return a.sign; } else { - return (a.mag != b.mag) & ((a.mag < b.mag) ^ a.sign); + return a.mag != b.mag && (a.mag < b.mag) ^ a.sign; } } @@ -399,7 +399,7 @@ fn i8_lt(a: i8, b: i8) -> bool { // # Returns // * `bool` - `true` if `a` is less than or equal to `b`, `false` otherwise. fn i8_le(a: i8, b: i8) -> bool { - if ((a == b) | (i8_lt(a, b) == true)) { + if (a == b || i8_lt(a, b) == true) { return true; } else { return false; @@ -413,7 +413,7 @@ fn i8_le(a: i8, b: i8) -> bool { // # Returns // * `bool` - `true` if `a` is greater than or equal to `b`, `false` otherwise. fn i8_ge(a: i8, b: i8) -> bool { - if ((a == b) | (i8_gt(a, b) == true)) { + if (a == b || i8_gt(a, b) == true) { return true; } else { return false; diff --git a/src/operators/tensor/helpers.cairo b/src/operators/tensor/helpers.cairo index fb0383fba..f0b340f50 100644 --- a/src/operators/tensor/helpers.cairo +++ b/src/operators/tensor/helpers.cairo @@ -65,7 +65,7 @@ fn check_compatibility(mut shape_1: Span, mut shape_2: Span) { let shape_2_val = *shape_2.pop_front().unwrap(); assert( - (shape_1_val == shape_2_val) | (shape_1_val == 1) | (shape_2_val == 1), + shape_1_val == shape_2_val || shape_1_val == 1 || shape_2_val == 1, 'tensors shape must match' ); }; @@ -291,7 +291,7 @@ fn broadcast_shape(mut shape1: Span, mut shape2: Span) -> Span, is_first_tensor: bool) -> Span { let ndim = shape.len(); - if (ndim == 1) & is_first_tensor { + if ndim == 1 && is_first_tensor { // Prepend 1 to shape if it's 1-dimensional let mut shape_adjusted = ArrayTrait::new(); shape_adjusted.append(1); @@ -37,7 +37,7 @@ fn prepare_shape_for_matmul(mut shape: Span, is_first_tensor: bool) -> Sp }; return shape_adjusted.span(); - } else if (ndim == 1) & !is_first_tensor { + } else if ndim == 1 && !is_first_tensor { // Append 1 to shape if it's 1-dimensional let mut shape_adjusted = ArrayTrait::new(); loop { diff --git a/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo b/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo index 8f072a60d..b90ce0bd9 100644 --- a/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo +++ b/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo @@ -20,10 +20,10 @@ fn matmul(self: @Tensor, other: @Tensor) -> Tensor, other: @Tensor) -> Tensor, other: @Tensor) -> Tensor { let self_ndim = (self_shape).len(); let other_ndim = (other_shape).len(); - assert((self_ndim <= 2) | (other_ndim <= 2), 'supports only 1D and 2D matmul'); + assert(self_ndim <= 2 || other_ndim <= 2, 'supports only 1D and 2D matmul'); //! Case: Both tensors are 1-dimensional - if (self_ndim == 1) & (other_ndim == 1) { + if self_ndim == 1 && other_ndim == 1 { let dot = dot_product((*self).data, (*other).data); let mut result_shape = ArrayTrait::new(); let mut result_data = ArrayTrait::new(); diff --git a/src/operators/tensor/linalg/matmul/matmul_u32.cairo b/src/operators/tensor/linalg/matmul/matmul_u32.cairo index ba9e1c95a..126c93a23 100644 --- a/src/operators/tensor/linalg/matmul/matmul_u32.cairo +++ b/src/operators/tensor/linalg/matmul/matmul_u32.cairo @@ -16,10 +16,10 @@ fn matmul(self: @Tensor, other: @Tensor) -> Tensor { let self_ndim = (self_shape).len(); let other_ndim = (other_shape).len(); - assert((self_ndim <= 2) | (other_ndim <= 2), 'supports only 1D and 2D matmul'); + assert(self_ndim <= 2 || other_ndim <= 2, 'supports only 1D and 2D matmul'); //! Case: Both tensors are 1-dimensional - if (self_ndim == 1) & (other_ndim == 1) { + if self_ndim == 1 && other_ndim == 1 { let dot = dot_product((*self).data, (*other).data); let mut result_shape = ArrayTrait::new(); let mut result_data = ArrayTrait::new(); diff --git a/src/operators/tensor/math/argmax/helpers.cairo b/src/operators/tensor/math/argmax/helpers.cairo index 39c0afac4..cb9810e9c 100644 --- a/src/operators/tensor/math/argmax/helpers.cairo +++ b/src/operators/tensor/math/argmax/helpers.cairo @@ -50,7 +50,7 @@ fn find_argmax_1D< max = current_value; max_index = count; } else { - if select_last_index & (current_value == max) { + if select_last_index && current_value == max { max_index = count; } }; @@ -108,7 +108,7 @@ fn find_argmax< let (new_max_value, new_argmax) = if ele > max_value { (ele, axis_index) } else { - if select_last_index & (ele == max_value) { + if select_last_index && ele == max_value { (ele, axis_index) } else { (max_value, argmax) diff --git a/src/operators/tensor/math/argmin/helpers.cairo b/src/operators/tensor/math/argmin/helpers.cairo index 52f9b9f4f..e76d9720c 100644 --- a/src/operators/tensor/math/argmin/helpers.cairo +++ b/src/operators/tensor/math/argmin/helpers.cairo @@ -54,7 +54,7 @@ fn find_argmin_1D< T, min_index = count; } else { - if select_last_index & (current_value == min) { + if select_last_index && current_value == min { min_index = count; } }; @@ -110,7 +110,7 @@ fn find_argmin< T, let (new_min_value, new_argmin) = if ele < min_value { (ele, axis_index) } else { - if select_last_index & (ele == min_value) { + if select_last_index && ele == min_value { (ele, axis_index) } else { (min_value, argmin) diff --git a/src/tests/operators/nn/functional/linear/linear_test.cairo b/src/tests/operators/nn/functional/linear/linear_test.cairo index a14cc4d7c..224d4f3ee 100644 --- a/src/tests/operators/nn/functional/linear/linear_test.cairo +++ b/src/tests/operators/nn/functional/linear/linear_test.cairo @@ -47,21 +47,21 @@ fn linear_test() { // TEST UNQUANTIZED let result = NNTrait::linear(inputs, weights, bias, false).data; assert( - (*result.at(0_usize).mag == 5541_u32) & (*result.at(0_usize).sign == false), + *result.at(0_usize).mag == 5541_u32 && *result.at(0_usize).sign == false, 'result[0] = 5541' ); assert( - (*result.at(1_usize).mag == 260_u32) & (*result.at(1_usize).sign == true), + *result.at(1_usize).mag == 260_u32 && *result.at(1_usize).sign == true, 'result[1] = -260' ); // TEST QUANTIZED let result = NNTrait::linear(inputs, weights, bias, true).data; assert( - (*result.at(0_usize).mag == 127_u32) & (*result.at(0_usize).sign == false), + *result.at(0_usize).mag == 127_u32 && *result.at(0_usize).sign == false, 'result[0] = 127' ); assert( - (*result.at(1_usize).mag == 6_u32) & (*result.at(1_usize).sign == true), 'result[1] = -6' + *result.at(1_usize).mag == 6_u32 && *result.at(1_usize).sign == true, 'result[1] = -6' ); } From 73637acdbc058bae7c072ea820da6dc2ac1fca21 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 20:28:10 +0300 Subject: [PATCH 019/126] remove _u32 in numbers --- docs/apis/numbers/signed-integer/int.abs.md | 2 +- .../numbers/signed-integer/int.div_rem.md | 4 +- docs/apis/numbers/signed-integer/int.max.md | 4 +- docs/apis/numbers/signed-integer/int.min.md | 4 +- docs/apis/operators/tensor/tensor.ln.md | 8 +- docs/apis/operators/tensor/tensor.new.md | 30 +-- src/numbers/signed_integer/i32.cairo | 34 +-- .../signed_integer/integer_trait.cairo | 14 +- .../sigmoid/sigmoid_i32/fp16x16.cairo | 2 +- .../sigmoid/sigmoid_i32/fp8x23.cairo | 2 +- src/operators/tensor/core.cairo | 38 +-- .../tensor/math/argmax/argmax_i32.cairo | 2 +- .../tensor/math/argmin/argmin_i32.cairo | 2 +- .../tensor/math/argmin/argmin_u32.cairo | 2 +- src/operators/tensor/math/max/max_i32.cairo | 2 +- src/operators/tensor/math/max/max_u32.cairo | 2 +- src/operators/tensor/math/min/min_i32.cairo | 2 +- src/operators/tensor/math/min/min_u32.cairo | 2 +- .../functional/quantization/quant_i32.cairo | 10 +- .../functional/quantization/quant_u32.cairo | 2 +- src/tests/numbers/signed_integer_test.cairo | 172 +++++++------- .../math/argmax/argmax_i32_test.cairo | 48 ++-- .../math/argmin/argmin_i32_test.cairo | 62 ++--- .../operators/math/equal/equal_u32_test.cairo | 66 +++--- .../math/greater/greater_u32_test.cairo | 66 +++--- .../greater_equal_u32_test.cairo | 66 +++--- .../operators/math/less/less_u32_test.cairo | 66 +++--- .../math/less_equal/less_equal_u32_test.cairo | 66 +++--- src/tests/operators/math/ln_test.cairo | 8 +- src/tests/operators/math/max_test.cairo | 2 +- src/tests/operators/math/min_test.cairo | 2 +- .../operators/math/reduce_sum_test.cairo | 24 +- .../leaky_relu/leaky_relu_i32_test.cairo | 12 +- .../leaky_relu/leaky_relu_u32_test.cairo | 14 +- .../nn/functional/linear/linear_test.cairo | 30 +-- .../nn/functional/relu/relu_i32_test.cairo | 12 +- .../nn/functional/relu/relu_u32_test.cairo | 10 +- .../functional/sigmoid/sigmoid_i32_test.cairo | 8 +- .../functional/sigmoid/sigmoid_u32_test.cairo | 8 +- .../softplus/softplus_i32_test.cairo | 8 +- .../softplus/softplus_u32_test.cairo | 8 +- .../softsign/softsign_i32_test.cairo | 8 +- .../softsign/softsign_u32_test.cairo | 8 +- .../tensor/helpers/helpers_i32.cairo | 102 ++++---- src/tests/operators/tensor/tensor_test.cairo | 224 +++++++++--------- src/tests/performance/quantization_test.cairo | 24 +- 46 files changed, 646 insertions(+), 646 deletions(-) diff --git a/docs/apis/numbers/signed-integer/int.abs.md b/docs/apis/numbers/signed-integer/int.abs.md index b91f5d5cc..d056a5620 100644 --- a/docs/apis/numbers/signed-integer/int.abs.md +++ b/docs/apis/numbers/signed-integer/int.abs.md @@ -19,7 +19,7 @@ A signed integer ``, representing the absolute value of `self` . ```rust fn abs_example() -> i32 { // We instantiate signed integers here. -let int = IntegerTrait::::new(42_u32, true); +let int = IntegerTrait::::new(42, true); // We can call `abs` function as follows. a.abs() diff --git a/docs/apis/numbers/signed-integer/int.div_rem.md b/docs/apis/numbers/signed-integer/int.div_rem.md index f2000d4fb..d47a9656a 100644 --- a/docs/apis/numbers/signed-integer/int.div_rem.md +++ b/docs/apis/numbers/signed-integer/int.div_rem.md @@ -24,8 +24,8 @@ A tuple of signed integer ``, containing the quotient and the remainder of th ```rust fn div_rem_example() -> (i32, i32) { // We instantiate signed integers here. -let a = IntegerTrait::::new(13_u32, false); -let b = IntegerTrait::::new(5_u32, false); +let a = IntegerTrait::::new(13, false); +let b = IntegerTrait::::new(5, false); // We can call `div_rem` function as follows. a.div_rem(b) diff --git a/docs/apis/numbers/signed-integer/int.max.md b/docs/apis/numbers/signed-integer/int.max.md index b4bbd92fb..9f4e365d8 100644 --- a/docs/apis/numbers/signed-integer/int.max.md +++ b/docs/apis/numbers/signed-integer/int.max.md @@ -20,8 +20,8 @@ A signed integer ``, The maximum between `self` and `other`. ```rust fn max_example() -> i32 { // We instantiate signed integer here. -let a = IntegerTrait::::new(42_u32, true); -let b = IntegerTrait::::new(13_u32, false); +let a = IntegerTrait::::new(42, true); +let b = IntegerTrait::::new(13, false); // We can call `max` function as follows. a.max(b) diff --git a/docs/apis/numbers/signed-integer/int.min.md b/docs/apis/numbers/signed-integer/int.min.md index ce40c20af..b0c30cbfd 100644 --- a/docs/apis/numbers/signed-integer/int.min.md +++ b/docs/apis/numbers/signed-integer/int.min.md @@ -21,8 +21,8 @@ A signed integer ``, The minimum between `self` and `other`. ```rust fn min_example() -> i32 { // We instantiate signed integer here. -let a = IntegerTrait::::new(42_u32, true); -let b = IntegerTrait::::new(13_u32, false); +let a = IntegerTrait::::new(42, true); +let b = IntegerTrait::::new(13, false); // We can call `max` function as follows. a.min(b) diff --git a/docs/apis/operators/tensor/tensor.ln.md b/docs/apis/operators/tensor/tensor.ln.md index 9b16faef3..682d579d4 100644 --- a/docs/apis/operators/tensor/tensor.ln.md +++ b/docs/apis/operators/tensor/tensor.ln.md @@ -27,10 +27,10 @@ let mut sizes = ArrayTrait::new(); sizes.append(4); let mut data = ArrayTrait::new(); -data.append(IntegerTrait::new(1_u32, false)); -data.append(IntegerTrait::new(2_u32, false)); -data.append(IntegerTrait::new(3_u32, false)); -data.append(IntegerTrait::new(100_u32, false)); +data.append(IntegerTrait::new(1, false)); +data.append(IntegerTrait::new(2, false)); +data.append(IntegerTrait::new(3, false)); +data.append(IntegerTrait::new(100, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra) diff --git a/docs/apis/operators/tensor/tensor.new.md b/docs/apis/operators/tensor/tensor.new.md index 4f65a3cc5..dc7955a2c 100644 --- a/docs/apis/operators/tensor/tensor.new.md +++ b/docs/apis/operators/tensor/tensor.new.md @@ -31,9 +31,9 @@ let mut shape = ArrayTrait::new(); shape.append(3); let mut data = ArrayTrait::new(); -data.append(0_u32); -data.append(1_u32); -data.append(2_u32); +data.append(0); +data.append(1); +data.append(2); let extra = Option::::None(()); @@ -49,10 +49,10 @@ shape.append(2); shape.append(2); let mut data = ArrayTrait::new(); -data.append(0_u32); -data.append(1_u32); -data.append(2_u32); -data.append(3_u32); +data.append(0); +data.append(1); +data.append(2); +data.append(3); let extra = Option::::None(()); @@ -69,14 +69,14 @@ shape.append(2); shape.append(2); let mut data = ArrayTrait::new(); -data.append(0_u32); -data.append(1_u32); -data.append(2_u32); -data.append(3_u32); -data.append(4_u32); -data.append(5_u32); -data.append(6_u32); -data.append(7_u32); +data.append(0); +data.append(1); +data.append(2); +data.append(3); +data.append(4); +data.append(5); +data.append(6); +data.append(7); let extra = Option::::None(()); diff --git a/src/numbers/signed_integer/i32.cairo b/src/numbers/signed_integer/i32.cairo index 01d55f151..46e7ab7d6 100644 --- a/src/numbers/signed_integer/i32.cairo +++ b/src/numbers/signed_integer/i32.cairo @@ -166,7 +166,7 @@ impl i32Neg of Neg { // # Panics // Panics if `x` is zero and has a sign that is not false. fn i32_check_sign_zero(x: i32) { - if x.mag == 0_u32 { + if x.mag == 0 { assert(x.sign == false, 'sign of 0 must be false'); } } @@ -174,9 +174,9 @@ fn i32_check_sign_zero(x: i32) { /// Cf: IntegerTrait::new docstring fn i32_new(mag: u32, sign: bool) -> i32 { if sign == true { - assert(mag <= 2147483648_u32, 'int: out of range'); + assert(mag <= 2147483648, 'int: out of range'); } else { - assert(mag <= 2147483647_u32, 'int: out of range'); + assert(mag <= 2147483647, 'int: out of range'); } i32 { mag, sign } } @@ -195,7 +195,7 @@ fn i32_add(a: i32, b: i32) -> i32 { // the sum of their absolute values can be returned. if a.sign == b.sign { let sum = a.mag + b.mag; - if (sum == 0_u32) { + if (sum == 0) { return IntegerTrait::new(sum, false); } return IntegerTrait::new(sum, a.sign); @@ -209,7 +209,7 @@ fn i32_add(a: i32, b: i32) -> i32 { }; let difference = larger.mag - smaller.mag; - if (difference == 0_u32) { + if (difference == 0) { return IntegerTrait::new(difference, false); } return IntegerTrait::new(difference, larger.sign); @@ -226,7 +226,7 @@ fn i32_sub(a: i32, b: i32) -> i32 { i32_check_sign_zero(a); i32_check_sign_zero(b); - if (b.mag == 0_u32) { + if (b.mag == 0) { return a; } @@ -254,7 +254,7 @@ fn i32_mul(a: i32, b: i32) -> i32 { // The product is the product of the absolute values of the operands. let mag = a.mag * b.mag; - if (mag == 0_u32) { + if (mag == 0) { return IntegerTrait::new(mag, false); } @@ -270,7 +270,7 @@ fn i32_mul(a: i32, b: i32) -> i32 { fn i32_div(a: i32, b: i32) -> i32 { i32_check_sign_zero(a); // Check that the divisor is not zero. - assert(b.mag != 0_u32, 'b can not be 0'); + assert(b.mag != 0, 'b can not be 0'); // The sign of the quotient is the XOR of the signs of the operands. let sign = a.sign ^ b.sign; @@ -282,27 +282,27 @@ fn i32_div(a: i32, b: i32) -> i32 { // If the operands have different signs, rounding is necessary. // First, check if the quotient is an integer. - if (a.mag % b.mag == 0_u32) { + if (a.mag % b.mag == 0) { let quotient = a.mag / b.mag; - if (quotient == 0_u32) { + if (quotient == 0) { return IntegerTrait::new(quotient, false); } return IntegerTrait::new(quotient, sign); } // If the quotient is not an integer, multiply the dividend by 10 to move the decimal point over. - let quotient = (a.mag * 10_u32) / b.mag; - let last_digit = quotient % 10_u32; + let quotient = (a.mag * 10) / b.mag; + let last_digit = quotient % 10; - if (quotient == 0_u32) { + if (quotient == 0) { return IntegerTrait::new(quotient, false); } // Check the last digit to determine rounding direction. - if (last_digit <= 5_u32) { - return IntegerTrait::new(quotient / 10_u32, sign); + if (last_digit <= 5) { + return IntegerTrait::new(quotient / 10, sign); } else { - return IntegerTrait::new((quotient / 10_u32) + 1_u32, sign); + return IntegerTrait::new((quotient / 10) + 1, sign); } } @@ -315,7 +315,7 @@ fn i32_div(a: i32, b: i32) -> i32 { fn i32_rem(a: i32, b: i32) -> i32 { i32_check_sign_zero(a); // Check that the divisor is not zero. - assert(b.mag != 0_u32, 'b can not be 0'); + assert(b.mag != 0, 'b can not be 0'); return a - (b * (a / b)); } diff --git a/src/numbers/signed_integer/integer_trait.cairo b/src/numbers/signed_integer/integer_trait.cairo index 7b42e9dbd..8757313bb 100644 --- a/src/numbers/signed_integer/integer_trait.cairo +++ b/src/numbers/signed_integer/integer_trait.cairo @@ -72,8 +72,8 @@ trait IntegerTrait { /// ```rust /// fn div_rem_example() -> (i32, i32) { /// // We instantiate signed integers here. - /// let a = IntegerTrait::::new(13_u32, false); - /// let b = IntegerTrait::::new(5_u32, false); + /// let a = IntegerTrait::::new(13, false); + /// let b = IntegerTrait::::new(5, false); /// /// // We can call `div_rem` function as follows. /// a.div_rem(b) @@ -103,7 +103,7 @@ trait IntegerTrait { /// ```rust /// fn abs_example() -> i32 { /// // We instantiate signed integers here. - /// let int = IntegerTrait::::new(42_u32, true); + /// let int = IntegerTrait::::new(42, true); /// /// // We can call `abs` function as follows. /// a.abs() @@ -134,8 +134,8 @@ trait IntegerTrait { /// ```rust /// fn max_example() -> i32 { /// // We instantiate signed integer here. - /// let a = IntegerTrait::::new(42_u32, true); - /// let b = IntegerTrait::::new(13_u32, false); + /// let a = IntegerTrait::::new(42, true); + /// let b = IntegerTrait::::new(13, false); /// /// // We can call `max` function as follows. /// a.max(b) @@ -167,8 +167,8 @@ trait IntegerTrait { /// ```rust /// fn min_example() -> i32 { /// // We instantiate signed integer here. - /// let a = IntegerTrait::::new(42_u32, true); - /// let b = IntegerTrait::::new(13_u32, false); + /// let a = IntegerTrait::::new(42, true); + /// let b = IntegerTrait::::new(13, false); /// /// // We can call `max` function as follows. /// a.min(b) diff --git a/src/operators/nn/functional/sigmoid/sigmoid_i32/fp16x16.cairo b/src/operators/nn/functional/sigmoid/sigmoid_i32/fp16x16.cairo index 1e97860c6..1bb6a0183 100644 --- a/src/operators/nn/functional/sigmoid/sigmoid_i32/fp16x16.cairo +++ b/src/operators/nn/functional/sigmoid/sigmoid_i32/fp16x16.cairo @@ -22,7 +22,7 @@ fn sigmoid_i32(z: @Tensor) -> Tensor { break (); }; - let current_index = *data.pop_front().unwrap() * IntegerTrait::new(1_u32, true); + let current_index = *data.pop_front().unwrap() * IntegerTrait::new(1, true); let fp_current_index = FixedTrait::new_unscaled( current_index.mag.into(), current_index.sign ); diff --git a/src/operators/nn/functional/sigmoid/sigmoid_i32/fp8x23.cairo b/src/operators/nn/functional/sigmoid/sigmoid_i32/fp8x23.cairo index 0a0ddf1df..b3c07a223 100644 --- a/src/operators/nn/functional/sigmoid/sigmoid_i32/fp8x23.cairo +++ b/src/operators/nn/functional/sigmoid/sigmoid_i32/fp8x23.cairo @@ -23,7 +23,7 @@ fn sigmoid_i32(z: @Tensor) -> Tensor { break (); }; - let current_index = *data.pop_front().unwrap() * IntegerTrait::new(1_u32, true); + let current_index = *data.pop_front().unwrap() * IntegerTrait::new(1, true); let fp_current_index = FixedTrait::new_unscaled( current_index.mag.into(), current_index.sign ); diff --git a/src/operators/tensor/core.cairo b/src/operators/tensor/core.cairo index 9031f3acc..571b4e95f 100644 --- a/src/operators/tensor/core.cairo +++ b/src/operators/tensor/core.cairo @@ -76,9 +76,9 @@ trait TensorTrait { /// shape.append(3); /// /// let mut data = ArrayTrait::new(); - /// data.append(0_u32); - /// data.append(1_u32); - /// data.append(2_u32); + /// data.append(0); + /// data.append(1); + /// data.append(2); /// /// let extra = Option::::None(()); /// @@ -94,10 +94,10 @@ trait TensorTrait { /// shape.append(2); /// /// let mut data = ArrayTrait::new(); - /// data.append(0_u32); - /// data.append(1_u32); - /// data.append(2_u32); - /// data.append(3_u32); + /// data.append(0); + /// data.append(1); + /// data.append(2); + /// data.append(3); /// /// let extra = Option::::None(()); /// @@ -114,14 +114,14 @@ trait TensorTrait { /// shape.append(2); /// /// let mut data = ArrayTrait::new(); - /// data.append(0_u32); - /// data.append(1_u32); - /// data.append(2_u32); - /// data.append(3_u32); - /// data.append(4_u32); - /// data.append(5_u32); - /// data.append(6_u32); - /// data.append(7_u32); + /// data.append(0); + /// data.append(1); + /// data.append(2); + /// data.append(3); + /// data.append(4); + /// data.append(5); + /// data.append(6); + /// data.append(7); /// /// let extra = Option::::None(()); /// @@ -746,10 +746,10 @@ trait TensorTrait { /// sizes.append(4); /// /// let mut data = ArrayTrait::new(); - /// data.append(IntegerTrait::new(1_u32, false)); - /// data.append(IntegerTrait::new(2_u32, false)); - /// data.append(IntegerTrait::new(3_u32, false)); - /// data.append(IntegerTrait::new(100_u32, false)); + /// data.append(IntegerTrait::new(1, false)); + /// data.append(IntegerTrait::new(2, false)); + /// data.append(IntegerTrait::new(3, false)); + /// data.append(IntegerTrait::new(100, false)); /// let extra = Option::::None(()); /// let tensor = TensorTrait::::new(sizes.span(), data.span(), extra) /// diff --git a/src/operators/tensor/math/argmax/argmax_i32.cairo b/src/operators/tensor/math/argmax/argmax_i32.cairo index f91d1bb33..abe604f2b 100644 --- a/src/operators/tensor/math/argmax/argmax_i32.cairo +++ b/src/operators/tensor/math/argmax/argmax_i32.cairo @@ -33,7 +33,7 @@ fn argmax( let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); - let MIN = IntegerTrait::::new(2147483648_u32, true); + let MIN = IntegerTrait::::new(2147483648, true); let mut index: usize = 0; loop { diff --git a/src/operators/tensor/math/argmin/argmin_i32.cairo b/src/operators/tensor/math/argmin/argmin_i32.cairo index 2a5764723..d56a4e260 100644 --- a/src/operators/tensor/math/argmin/argmin_i32.cairo +++ b/src/operators/tensor/math/argmin/argmin_i32.cairo @@ -37,7 +37,7 @@ fn argmin( let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); - let MAX = IntegerTrait::::new(2147483647_u32, false); + let MAX = IntegerTrait::::new(2147483647, false); let mut index: usize = 0; loop { diff --git a/src/operators/tensor/math/argmin/argmin_u32.cairo b/src/operators/tensor/math/argmin/argmin_u32.cairo index b5c09a384..9fd053f79 100644 --- a/src/operators/tensor/math/argmin/argmin_u32.cairo +++ b/src/operators/tensor/math/argmin/argmin_u32.cairo @@ -36,7 +36,7 @@ fn argmin( let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); - let MAX = 4294967295_u32; // 2 ** 32 - 1 + let MAX = 4294967295; // 2 ** 32 - 1 let mut index: usize = 0; loop { diff --git a/src/operators/tensor/math/max/max_i32.cairo b/src/operators/tensor/math/max/max_i32.cairo index efa231581..959665025 100644 --- a/src/operators/tensor/math/max/max_i32.cairo +++ b/src/operators/tensor/math/max/max_i32.cairo @@ -6,7 +6,7 @@ use orion::utils::check_gas; /// Cf: TensorTrait::max docstring fn max_in_tensor(mut vec: Span::) -> i32 { - let mut max_value: i32 = IntegerTrait::new(2147483647_u32, true); + let mut max_value: i32 = IntegerTrait::new(2147483647, true); loop { check_gas(); diff --git a/src/operators/tensor/math/max/max_u32.cairo b/src/operators/tensor/math/max/max_u32.cairo index 83d796ba6..64fa359f0 100644 --- a/src/operators/tensor/math/max/max_u32.cairo +++ b/src/operators/tensor/math/max/max_u32.cairo @@ -5,7 +5,7 @@ use orion::utils::check_gas; /// Cf: TensorTrait::max docstring fn max_in_tensor(mut vec: Span::) -> u32 { - let mut max_value = 0_u32; + let mut max_value = 0; loop { check_gas(); diff --git a/src/operators/tensor/math/min/min_i32.cairo b/src/operators/tensor/math/min/min_i32.cairo index 230203bdf..04d857e0c 100644 --- a/src/operators/tensor/math/min/min_i32.cairo +++ b/src/operators/tensor/math/min/min_i32.cairo @@ -6,7 +6,7 @@ use orion::utils::check_gas; /// Cf: TensorTrait::min docstring fn min_in_tensor(mut vec: Span::) -> i32 { - let mut min_value: i32 = IntegerTrait::new(2147483647_u32, false); + let mut min_value: i32 = IntegerTrait::new(2147483647, false); loop { check_gas(); diff --git a/src/operators/tensor/math/min/min_u32.cairo b/src/operators/tensor/math/min/min_u32.cairo index a99356775..ec03576de 100644 --- a/src/operators/tensor/math/min/min_u32.cairo +++ b/src/operators/tensor/math/min/min_u32.cairo @@ -6,7 +6,7 @@ use orion::utils::check_gas; /// Cf: TensorTrait::min docstring fn min_in_tensor(mut vec: Span::) -> u32 { - let mut min_value = 4294967295_u32; + let mut min_value = 4294967295; loop { check_gas(); diff --git a/src/performance/functional/quantization/quant_i32.cairo b/src/performance/functional/quantization/quant_i32.cairo index e5e9e2b73..2058a401d 100644 --- a/src/performance/functional/quantization/quant_i32.cairo +++ b/src/performance/functional/quantization/quant_i32.cairo @@ -27,23 +27,23 @@ use orion::utils::fp8x23_to_i32; fn symetric_quant(min_val: i32, max_val: i32, data: i32) -> i32 { // Define quantization range // int8 range : [-127;127] - let q_min_int = IntegerTrait::new(127_u32, true); - let q_max_int = IntegerTrait::new(127_u32, false); + let q_min_int = IntegerTrait::new(127, true); + let q_max_int = IntegerTrait::new(127, false); - let factor = IntegerTrait::new(1000_u32, false); + let factor = IntegerTrait::new(1000, false); let min_val = min_val * factor; let max_val = max_val * factor; // Calculate the scale based on 8 bit symetric quantization // scale = max(abs(data_range_max), abs(data_range_min)) * 2 / (quantization_range_max - quantization_range_min) - let scale = ((min_val.abs()).max(max_val.abs()) * IntegerTrait::new(2_u32, false)) + let scale = ((min_val.abs()).max(max_val.abs()) * IntegerTrait::new(2, false)) / (q_max_int - q_min_int); // Quantize data based on the scale let quantized_data = (data * factor) / scale; - assert(quantized_data.mag <= 127_u32, 'out of range'); + assert(quantized_data.mag <= 127, 'out of range'); return quantized_data; } diff --git a/src/performance/functional/quantization/quant_u32.cairo b/src/performance/functional/quantization/quant_u32.cairo index ff282a21d..d08bc4527 100644 --- a/src/performance/functional/quantization/quant_u32.cairo +++ b/src/performance/functional/quantization/quant_u32.cairo @@ -42,7 +42,7 @@ fn symetric_quant(min_val: u32, max_val: u32, data: u32) -> u32 { // Quantize data based on the scale let quantized_data = (data * factor) / scale; - assert(quantized_data <= 255_u32, 'out of range'); + assert(quantized_data <= 255, 'out of range'); return quantized_data; } diff --git a/src/tests/numbers/signed_integer_test.cairo b/src/tests/numbers/signed_integer_test.cairo index 73a0216c0..f964f3a03 100644 --- a/src/tests/numbers/signed_integer_test.cairo +++ b/src/tests/numbers/signed_integer_test.cairo @@ -3,114 +3,114 @@ use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; #[test] fn test_into() { - let x = IntegerTrait::::new(42_u32, false); + let x = IntegerTrait::::new(42, false); assert(x.into() == 42, 'should convert to felt252'); - let x = IntegerTrait::::new(42_u32, true); + let x = IntegerTrait::::new(42, true); assert(x.into() == -42, 'should convert to felt252'); } #[test] fn test_add() { // Test addition of two positive integers - let a = IntegerTrait::::new(42_u32, false); - let b = IntegerTrait::::new(13_u32, false); + let a = IntegerTrait::::new(42, false); + let b = IntegerTrait::::new(13, false); let result = a + b; - assert(result.mag == 55_u32, '42 + 13 = 55'); + assert(result.mag == 55, '42 + 13 = 55'); assert(result.sign == false, '42 + 13 -> positive'); // Test addition of two negative integers - let a = IntegerTrait::::new(42_u32, true); - let b = IntegerTrait::::new(13_u32, true); + let a = IntegerTrait::::new(42, true); + let b = IntegerTrait::::new(13, true); let result = a + b; - assert(result.mag == 55_u32, '-42 - 13 = -55'); + assert(result.mag == 55, '-42 - 13 = -55'); assert(result.sign == true, '-42 - 13 -> negative'); // Test addition of a positive integer and a negative integer with the same magnitude - let a = IntegerTrait::::new(42_u32, false); - let b = IntegerTrait::::new(42_u32, true); + let a = IntegerTrait::::new(42, false); + let b = IntegerTrait::::new(42, true); let result = a + b; - assert(result.mag == 0_u32, '42 - 42 = 0'); + assert(result.mag == 0, '42 - 42 = 0'); assert(result.sign == false, '42 - 42 -> positive'); // Test addition of a positive integer and a negative integer with different magnitudes - let a = IntegerTrait::::new(42_u32, false); - let b = IntegerTrait::::new(13_u32, true); + let a = IntegerTrait::::new(42, false); + let b = IntegerTrait::::new(13, true); let result = a + b; - assert(result.mag == 29_u32, '42 - 13 = 29'); + assert(result.mag == 29, '42 - 13 = 29'); assert(result.sign == false, '42 - 13 -> positive'); // Test addition of a negative integer and a positive integer with different magnitudes - let a = IntegerTrait::::new(42_u32, true); - let b = IntegerTrait::::new(13_u32, false); + let a = IntegerTrait::::new(42, true); + let b = IntegerTrait::::new(13, false); let result = a + b; - assert(result.mag == 29_u32, '-42 + 13 = -29'); + assert(result.mag == 29, '-42 + 13 = -29'); assert(result.sign == true, '-42 + 13 -> negative'); } #[test] fn test_sub() { // Test subtraction of two positive integers with larger first - let a = IntegerTrait::::new(42_u32, false); - let b = IntegerTrait::::new(13_u32, false); + let a = IntegerTrait::::new(42, false); + let b = IntegerTrait::::new(13, false); let result = a - b; - assert(result.mag == 29_u32, '42 - 13 = 29'); + assert(result.mag == 29, '42 - 13 = 29'); assert(result.sign == false, '42 - 13 -> positive'); // Test subtraction of two positive integers with larger second - let a = IntegerTrait::::new(13_u32, false); - let b = IntegerTrait::::new(42_u32, false); + let a = IntegerTrait::::new(13, false); + let b = IntegerTrait::::new(42, false); let result = a - b; - assert(result.mag == 29_u32, '13 - 42 = -29'); + assert(result.mag == 29, '13 - 42 = -29'); assert(result.sign == true, '13 - 42 -> negative'); // Test subtraction of two negative integers with larger first - let a = IntegerTrait::::new(42_u32, true); - let b = IntegerTrait::::new(13_u32, true); + let a = IntegerTrait::::new(42, true); + let b = IntegerTrait::::new(13, true); let result = a - b; - assert(result.mag == 29_u32, '-42 - -13 = 29'); + assert(result.mag == 29, '-42 - -13 = 29'); assert(result.sign == true, '-42 - -13 -> negative'); // Test subtraction of two negative integers with larger second - let a = IntegerTrait::::new(13_u32, true); - let b = IntegerTrait::::new(42_u32, true); + let a = IntegerTrait::::new(13, true); + let b = IntegerTrait::::new(42, true); let result = a - b; - assert(result.mag == 29_u32, '-13 - -42 = 29'); + assert(result.mag == 29, '-13 - -42 = 29'); assert(result.sign == false, '-13 - -42 -> positive'); // Test subtraction of a positive integer and a negative integer with the same magnitude - let a = IntegerTrait::::new(42_u32, false); - let b = IntegerTrait::::new(42_u32, true); + let a = IntegerTrait::::new(42, false); + let b = IntegerTrait::::new(42, true); let result = a - b; - assert(result.mag == 84_u32, '42 - -42 = 84'); + assert(result.mag == 84, '42 - -42 = 84'); assert(result.sign == false, '42 - -42 -> postive'); // Test subtraction of a negative integer and a positive integer with the same magnitude - let a = IntegerTrait::::new(42_u32, true); - let b = IntegerTrait::::new(42_u32, false); + let a = IntegerTrait::::new(42, true); + let b = IntegerTrait::::new(42, false); let result = a - b; - assert(result.mag == 84_u32, '-42 - 42 = -84'); + assert(result.mag == 84, '-42 - 42 = -84'); assert(result.sign == true, '-42 - 42 -> negative'); // Test subtraction of a positive integer and a negative integer with different magnitudes - let a = IntegerTrait::::new(100_u32, false); - let b = IntegerTrait::::new(42_u32, true); + let a = IntegerTrait::::new(100, false); + let b = IntegerTrait::::new(42, true); let result = a - b; - assert(result.mag == 142_u32, '100 - - 42 = 142'); + assert(result.mag == 142, '100 - - 42 = 142'); assert(result.sign == false, '100 - - 42 -> postive'); // Test subtraction of a negative integer and a positive integer with different magnitudes - let a = IntegerTrait::::new(42_u32, true); - let b = IntegerTrait::::new(100_u32, false); + let a = IntegerTrait::::new(42, true); + let b = IntegerTrait::::new(100, false); let result = a - b; - assert(result.mag == 142_u32, '-42 - 100 = -142'); + assert(result.mag == 142, '-42 - 100 = -142'); assert(result.sign == true, '-42 - 100 -> negative'); // Test subtraction resulting in zero - let a = IntegerTrait::::new(42_u32, false); - let b = IntegerTrait::::new(42_u32, false); + let a = IntegerTrait::::new(42, false); + let b = IntegerTrait::::new(42, false); let result = a - b; - assert(result.mag == 0_u32, '42 - 42 = 0'); + assert(result.mag == 0, '42 - 42 = 0'); assert(result.sign == false, '42 - 42 -> positive'); } @@ -118,69 +118,69 @@ fn test_sub() { #[test] fn test_mul() { // Test multiplication of positive integers - let a = IntegerTrait::::new(10_u32, false); - let b = IntegerTrait::::new(5_u32, false); + let a = IntegerTrait::::new(10, false); + let b = IntegerTrait::::new(5, false); let result = a * b; - assert(result.mag == 50_u32, '10 * 5 = 50'); + assert(result.mag == 50, '10 * 5 = 50'); assert(result.sign == false, '10 * 5 -> positive'); // Test multiplication of negative integers - let a = IntegerTrait::::new(10_u32, true); - let b = IntegerTrait::::new(5_u32, true); + let a = IntegerTrait::::new(10, true); + let b = IntegerTrait::::new(5, true); let result = a * b; - assert(result.mag == 50_u32, '-10 * -5 = 50'); + assert(result.mag == 50, '-10 * -5 = 50'); assert(result.sign == false, '-10 * -5 -> positive'); // Test multiplication of positive and negative integers - let a = IntegerTrait::::new(10_u32, false); - let b = IntegerTrait::::new(5_u32, true); + let a = IntegerTrait::::new(10, false); + let b = IntegerTrait::::new(5, true); let result = a * b; - assert(result.mag == 50_u32, '10 * -5 = -50'); + assert(result.mag == 50, '10 * -5 = -50'); assert(result.sign == true, '10 * -5 -> negative'); // Test multiplication by zero - let a = IntegerTrait::::new(10_u32, false); - let b = IntegerTrait::::new(0_u32, false); + let a = IntegerTrait::::new(10, false); + let b = IntegerTrait::::new(0, false); let result = a * b; - assert(result.mag == 0_u32, '10 * 0 = 0'); + assert(result.mag == 0, '10 * 0 = 0'); assert(result.sign == false, '10 * 0 -> positive'); } #[test] fn test_div_no_rem() { // Test division of positive integers - let a = IntegerTrait::::new(10_u32, false); - let b = IntegerTrait::::new(5_u32, false); + let a = IntegerTrait::::new(10, false); + let b = IntegerTrait::::new(5, false); let result = a / b; - assert(result.mag == 2_u32, '10 // 5 = 2'); + assert(result.mag == 2, '10 // 5 = 2'); assert(result.sign == false, '10 // 5 -> positive'); // Test division of negative integers - let a = IntegerTrait::::new(10_u32, true); - let b = IntegerTrait::::new(5_u32, true); + let a = IntegerTrait::::new(10, true); + let b = IntegerTrait::::new(5, true); let result = a / b; - assert(result.mag == 2_u32, '-10 // -5 = 2'); + assert(result.mag == 2, '-10 // -5 = 2'); assert(result.sign == false, '-10 // -5 -> positive'); // Test division of positive and negative integers - let a = IntegerTrait::::new(10_u32, false); - let b = IntegerTrait::::new(5_u32, true); + let a = IntegerTrait::::new(10, false); + let b = IntegerTrait::::new(5, true); let result = a / b; - assert(result.mag == 2_u32, '10 // -5 = -2'); + assert(result.mag == 2, '10 // -5 = -2'); assert(result.sign == true, '10 // -5 -> negative'); // Test division with a = zero - let a = IntegerTrait::::new(0_u32, false); - let b = IntegerTrait::::new(10_u32, false); + let a = IntegerTrait::::new(0, false); + let b = IntegerTrait::::new(10, false); let result = a / b; - assert(result.mag == 0_u32, '0 // 10 = 0'); + assert(result.mag == 0, '0 // 10 = 0'); assert(result.sign == false, '0 // 10 -> positive'); // Test division with a = zero - let a = IntegerTrait::::new(0_u32, false); - let b = IntegerTrait::::new(10_u32, false); + let a = IntegerTrait::::new(0, false); + let b = IntegerTrait::::new(10, false); let result = a / b; - assert(result.mag == 0_u32, '0 // 10 = 0'); + assert(result.mag == 0, '0 // 10 = 0'); assert(result.sign == false, '0 // 10 -> positive'); } @@ -188,37 +188,37 @@ fn test_div_no_rem() { #[available_gas(20000000)] fn test_div_rem() { // Test division and remainder of positive integers - let a = IntegerTrait::::new(13_u32, false); - let b = IntegerTrait::::new(5_u32, false); + let a = IntegerTrait::::new(13, false); + let b = IntegerTrait::::new(5, false); let (q, r) = a.div_rem(b); - assert(q.mag == 2_u32 && r.mag == 3_u32, '13 // 5 = 2 r 3'); + assert(q.mag == 2 && r.mag == 3, '13 // 5 = 2 r 3'); assert((q.sign == false) & (r.sign == false), '13 // 5 -> positive'); // Test division and remainder of negative integers - let a = IntegerTrait::::new(13_u32, true); - let b = IntegerTrait::::new(5_u32, true); + let a = IntegerTrait::::new(13, true); + let b = IntegerTrait::::new(5, true); let (q, r) = a.div_rem(b); - assert(q.mag == 2_u32 && r.mag == 3_u32, '-13 // -5 = 2 r -3'); + assert(q.mag == 2 && r.mag == 3, '-13 // -5 = 2 r -3'); assert(q.sign == false && r.sign == true, '-13 // -5 -> positive'); // Test division and remainder of positive and negative integers - let a = IntegerTrait::::new(13_u32, false); - let b = IntegerTrait::::new(5_u32, true); + let a = IntegerTrait::::new(13, false); + let b = IntegerTrait::::new(5, true); let (q, r) = a.div_rem(b); - assert(q.mag == 3_u32 && r.mag == 2_u32, '13 // -5 = -3 r -2'); + assert(q.mag == 3 && r.mag == 2, '13 // -5 = -3 r -2'); assert(q.sign == true && r.sign == true, '13 // -5 -> negative'); // Test division with a = zero - let a = IntegerTrait::::new(0_u32, false); - let b = IntegerTrait::::new(10_u32, false); + let a = IntegerTrait::::new(0, false); + let b = IntegerTrait::::new(10, false); let (q, r) = a.div_rem(b); - assert(q.mag == 0_u32 && r.mag == 0_u32, '0 // 10 = 0 r 0'); + assert(q.mag == 0 && r.mag == 0, '0 // 10 = 0 r 0'); assert(q.sign == false && r.sign == false, '0 // 10 -> positive'); // Test division and remainder with a negative dividend and positive divisor - let a = IntegerTrait::::new(13_u32, true); - let b = IntegerTrait::::new(5_u32, false); + let a = IntegerTrait::::new(13, true); + let b = IntegerTrait::::new(5, false); let (q, r) = a.div_rem(b); - assert(q.mag == 3_u32 && r.mag == 2_u32, '-13 // 5 = -3 r 2'); + assert(q.mag == 3 && r.mag == 2, '-13 // 5 = -3 r 2'); assert(q.sign == true && r.sign == false, '-13 // 5 -> negative'); } diff --git a/src/tests/operators/math/argmax/argmax_i32_test.cairo b/src/tests/operators/math/argmax/argmax_i32_test.cairo index 82fc5c120..4a2247354 100644 --- a/src/tests/operators/math/argmax/argmax_i32_test.cairo +++ b/src/tests/operators/math/argmax/argmax_i32_test.cairo @@ -18,9 +18,9 @@ mod tensor1D_argmax_i32 { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -32,9 +32,9 @@ mod tensor1D_argmax_i32 { let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -60,9 +60,9 @@ mod tensor1D_argmax_i32 { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -85,9 +85,9 @@ mod tensor1D_argmax_i32 { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(1, true)); + data.append(IntegerTrait::new(1, true)); + data.append(IntegerTrait::new(1, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -172,10 +172,10 @@ mod tensor2x2_argmax_i32 { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -278,14 +278,14 @@ mod tensor2x2x2_argmax_i32 { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); diff --git a/src/tests/operators/math/argmin/argmin_i32_test.cairo b/src/tests/operators/math/argmin/argmin_i32_test.cairo index 5e6786656..ac767e7e7 100644 --- a/src/tests/operators/math/argmin/argmin_i32_test.cairo +++ b/src/tests/operators/math/argmin/argmin_i32_test.cairo @@ -18,9 +18,9 @@ mod tensor1D_argmin_i32 { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -32,9 +32,9 @@ mod tensor1D_argmin_i32 { let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -60,9 +60,9 @@ mod tensor1D_argmin_i32 { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, true)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -85,9 +85,9 @@ mod tensor1D_argmin_i32 { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(1, true)); + data.append(IntegerTrait::new(1, true)); + data.append(IntegerTrait::new(1, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -103,9 +103,9 @@ mod tensor1D_argmin_i32 { let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(1_u32, true)); - data.append(IntegerTrait::new(1_u32, true)); + data.append(IntegerTrait::new(1, true)); + data.append(IntegerTrait::new(1, true)); + data.append(IntegerTrait::new(1, true)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -181,10 +181,10 @@ mod tensor2x2_argmin_i32 { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -202,10 +202,10 @@ mod tensor2x2_argmin_i32 { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -299,14 +299,14 @@ mod tensor2x2x2_argmin_i32 { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(1, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); diff --git a/src/tests/operators/math/equal/equal_u32_test.cairo b/src/tests/operators/math/equal/equal_u32_test.cairo index 3b362c11d..2de02866b 100644 --- a/src/tests/operators/math/equal/equal_u32_test.cairo +++ b/src/tests/operators/math/equal/equal_u32_test.cairo @@ -11,26 +11,26 @@ fn tensor_eq_u32() { sizes.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10_u32); - arr_2.append(11_u32); - arr_2.append(12_u32); - arr_2.append(13_u32); - arr_2.append(4_u32); - arr_2.append(5_u32); - arr_2.append(16_u32); - arr_2.append(17_u32); - arr_2.append(18_u32); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); let extra = Option::::None(()); @@ -63,23 +63,23 @@ fn tensor_eq_u32_broadcast() { sizes_2.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); - arr_1.append(9_u32); - arr_1.append(10_u32); - arr_1.append(11_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0_u32); - arr_2.append(1_u32); - arr_2.append(2_u32); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); let extra = Option::::None(()); diff --git a/src/tests/operators/math/greater/greater_u32_test.cairo b/src/tests/operators/math/greater/greater_u32_test.cairo index 0bc034518..1aca92576 100644 --- a/src/tests/operators/math/greater/greater_u32_test.cairo +++ b/src/tests/operators/math/greater/greater_u32_test.cairo @@ -11,26 +11,26 @@ fn tensor_greater_u32() { sizes.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(7_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10_u32); - arr_2.append(11_u32); - arr_2.append(12_u32); - arr_2.append(13_u32); - arr_2.append(4_u32); - arr_2.append(5_u32); - arr_2.append(16_u32); - arr_2.append(17_u32); - arr_2.append(18_u32); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); let extra = Option::::None(()); @@ -76,23 +76,23 @@ fn tensor_greater_u32_broadcast() { sizes_2.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); - arr_1.append(9_u32); - arr_1.append(10_u32); - arr_1.append(11_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0_u32); - arr_2.append(1_u32); - arr_2.append(2_u32); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); let extra = Option::::None(()); diff --git a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo index 339f503df..1d7eb0d13 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo @@ -11,26 +11,26 @@ fn tensor_greater_equal_u32() { sizes.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(7_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10_u32); - arr_2.append(11_u32); - arr_2.append(12_u32); - arr_2.append(13_u32); - arr_2.append(4_u32); - arr_2.append(5_u32); - arr_2.append(16_u32); - arr_2.append(17_u32); - arr_2.append(18_u32); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); let extra = Option::::None(()); @@ -76,23 +76,23 @@ fn tensor_greater_equal_u32_broadcast() { sizes_2.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); - arr_1.append(9_u32); - arr_1.append(10_u32); - arr_1.append(11_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0_u32); - arr_2.append(1_u32); - arr_2.append(2_u32); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); let extra = Option::::None(()); diff --git a/src/tests/operators/math/less/less_u32_test.cairo b/src/tests/operators/math/less/less_u32_test.cairo index b173cc045..9bfbd3e4d 100644 --- a/src/tests/operators/math/less/less_u32_test.cairo +++ b/src/tests/operators/math/less/less_u32_test.cairo @@ -11,26 +11,26 @@ fn tensor_less_u32() { sizes.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(7_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10_u32); - arr_2.append(11_u32); - arr_2.append(12_u32); - arr_2.append(13_u32); - arr_2.append(4_u32); - arr_2.append(5_u32); - arr_2.append(16_u32); - arr_2.append(17_u32); - arr_2.append(18_u32); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); let extra = Option::::None(()); @@ -76,23 +76,23 @@ fn tensor_less_u32_broadcast() { sizes_2.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); - arr_1.append(9_u32); - arr_1.append(10_u32); - arr_1.append(11_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0_u32); - arr_2.append(1_u32); - arr_2.append(2_u32); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); let extra = Option::::None(()); diff --git a/src/tests/operators/math/less_equal/less_equal_u32_test.cairo b/src/tests/operators/math/less_equal/less_equal_u32_test.cairo index b2c5f5073..da59fb24d 100644 --- a/src/tests/operators/math/less_equal/less_equal_u32_test.cairo +++ b/src/tests/operators/math/less_equal/less_equal_u32_test.cairo @@ -11,26 +11,26 @@ fn tensor_less_equal_u32() { sizes.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(7_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10_u32); - arr_2.append(11_u32); - arr_2.append(12_u32); - arr_2.append(13_u32); - arr_2.append(4_u32); - arr_2.append(5_u32); - arr_2.append(16_u32); - arr_2.append(17_u32); - arr_2.append(18_u32); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); let extra = Option::::None(()); @@ -76,23 +76,23 @@ fn tensor_less_equal_u32_broadcast() { sizes_2.append(3); let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - arr_1.append(8_u32); - arr_1.append(9_u32); - arr_1.append(10_u32); - arr_1.append(11_u32); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0_u32); - arr_2.append(1_u32); - arr_2.append(2_u32); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); let extra = Option::::None(()); diff --git a/src/tests/operators/math/ln_test.cairo b/src/tests/operators/math/ln_test.cairo index 5c76d27a4..86fdcc67e 100644 --- a/src/tests/operators/math/ln_test.cairo +++ b/src/tests/operators/math/ln_test.cairo @@ -16,10 +16,10 @@ fn ln_test() { sizes.append(4); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(100_u32, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(100, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); diff --git a/src/tests/operators/math/max_test.cairo b/src/tests/operators/math/max_test.cairo index 40d491cd7..21002dc29 100644 --- a/src/tests/operators/math/max_test.cairo +++ b/src/tests/operators/math/max_test.cairo @@ -8,5 +8,5 @@ fn max_tensor() { let tensor = i32_tensor_2x2x2_helper(); let result = tensor.max().mag; - assert(result == 7_u32, 'tensor.max = 7'); + assert(result == 7, 'tensor.max = 7'); } diff --git a/src/tests/operators/math/min_test.cairo b/src/tests/operators/math/min_test.cairo index 2f1d35a85..afd2b7d2b 100644 --- a/src/tests/operators/math/min_test.cairo +++ b/src/tests/operators/math/min_test.cairo @@ -8,5 +8,5 @@ fn min_tensor() { let tensor = i32_tensor_2x2x2_helper(); let result = tensor.min().mag; - assert(result == 0_u32, 'tensor.min = 0'); + assert(result == 0, 'tensor.min = 0'); } diff --git a/src/tests/operators/math/reduce_sum_test.cairo b/src/tests/operators/math/reduce_sum_test.cairo index c18d963ce..145ca109d 100644 --- a/src/tests/operators/math/reduce_sum_test.cairo +++ b/src/tests/operators/math/reduce_sum_test.cairo @@ -23,22 +23,22 @@ fn reduce_sum_3d() { let result = tensor.reduce_sum(0, false); - assert(*result.data.at(0).mag == 4_u32, 'result[0] = 4'); - assert(*result.data.at(1).mag == 6_u32, 'result[1] = 6'); - assert(*result.data.at(2).mag == 8_u32, 'result[2] = 8'); - assert(*result.data.at(3).mag == 10_u32, 'result[3] = 10'); + assert(*result.data.at(0).mag == 4, 'result[0] = 4'); + assert(*result.data.at(1).mag == 6, 'result[1] = 6'); + assert(*result.data.at(2).mag == 8, 'result[2] = 8'); + assert(*result.data.at(3).mag == 10, 'result[3] = 10'); let result = tensor.reduce_sum(1, false).data; - assert(*result.at(0).mag == 2_u32, 'result[0] = 2'); - assert(*result.at(1).mag == 4_u32, 'result[1] = 4'); - assert(*result.at(2).mag == 10_u32, 'result[2] = 10'); - assert(*result.at(3).mag == 12_u32, 'result[3] = 12'); + assert(*result.at(0).mag == 2, 'result[0] = 2'); + assert(*result.at(1).mag == 4, 'result[1] = 4'); + assert(*result.at(2).mag == 10, 'result[2] = 10'); + assert(*result.at(3).mag == 12, 'result[3] = 12'); let result = tensor.reduce_sum(2, false).data; - assert(*result.at(0).mag == 1_u32, 'result[0] = 1'); - assert(*result.at(1).mag == 5_u32, 'result[1] = 5'); - assert(*result.at(2).mag == 9_u32, 'result[2] = 9'); - assert(*result.at(3).mag == 13_u32, 'result[3] = 13'); + assert(*result.at(0).mag == 1, 'result[0] = 1'); + assert(*result.at(1).mag == 5, 'result[1] = 5'); + assert(*result.at(2).mag == 9, 'result[2] = 9'); + assert(*result.at(3).mag == 13, 'result[3] = 13'); } diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo index f7ddef031..c45af6f86 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo @@ -19,12 +19,12 @@ fn leaky_relu_i32_test() { shape.append(3); let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(1_u32, false); - let val_2 = IntegerTrait::new(2_u32, false); - let val_3 = IntegerTrait::new(1_u32, true); - let val_4 = IntegerTrait::new(2_u32, true); - let val_5 = IntegerTrait::new(0_u32, false); - let val_6 = IntegerTrait::new(0_u32, false); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(0, false); data.append(val_1); data.append(val_2); diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo index d95b46563..e9ba81712 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo @@ -19,12 +19,12 @@ fn leaky_relu_u32_test() { shape.append(3); let mut data = ArrayTrait::::new(); - let val_1 = 4_u32; - let val_2 = 3_u32; - let val_3 = 2_u32; - let val_4 = 1_u32; - let val_5 = 0_u32; - let val_6 = 0_u32; + let val_1 = 4; + let val_2 = 3; + let val_3 = 2; + let val_4 = 1; + let val_5 = 0; + let val_6 = 0; data.append(val_1); data.append(val_2); @@ -37,7 +37,7 @@ fn leaky_relu_u32_test() { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let alpha = FixedTrait::new(838861, false); // 0.1 - let threshold = 3_u32; + let threshold = 3; let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); let data = *result.data.at(0); diff --git a/src/tests/operators/nn/functional/linear/linear_test.cairo b/src/tests/operators/nn/functional/linear/linear_test.cairo index 224d4f3ee..eea6d4e16 100644 --- a/src/tests/operators/nn/functional/linear/linear_test.cairo +++ b/src/tests/operators/nn/functional/linear/linear_test.cairo @@ -15,9 +15,9 @@ fn linear_test() { let mut shape = ArrayTrait::::new(); shape.append(3); let mut data = ArrayTrait::new(); - data.append(i32 { mag: 71_u32, sign: true }); - data.append(i32 { mag: 38_u32, sign: false }); - data.append(i32 { mag: 62_u32, sign: false }); + data.append(i32 { mag: 71, sign: true }); + data.append(i32 { mag: 38, sign: false }); + data.append(i32 { mag: 62, sign: false }); let extra = Option::::None(()); let inputs = TensorTrait::new(shape.span(), data.span(), extra); @@ -26,12 +26,12 @@ fn linear_test() { shape.append(2); shape.append(3); let mut data = ArrayTrait::new(); - data.append(i32 { mag: 8_u32, sign: true }); - data.append(i32 { mag: 64_u32, sign: false }); - data.append(i32 { mag: 40_u32, sign: false }); - data.append(i32 { mag: 33_u32, sign: true }); - data.append(i32 { mag: 34_u32, sign: true }); - data.append(i32 { mag: 20_u32, sign: true }); + data.append(i32 { mag: 8, sign: true }); + data.append(i32 { mag: 64, sign: false }); + data.append(i32 { mag: 40, sign: false }); + data.append(i32 { mag: 33, sign: true }); + data.append(i32 { mag: 34, sign: true }); + data.append(i32 { mag: 20, sign: true }); let extra = Option::::None(()); let weights = TensorTrait::new(shape.span(), data.span(), extra); @@ -39,29 +39,29 @@ fn linear_test() { let mut shape = ArrayTrait::::new(); shape.append(2); let mut data = ArrayTrait::new(); - data.append(i32 { mag: 61_u32, sign: false }); - data.append(i32 { mag: 71_u32, sign: true }); + data.append(i32 { mag: 61, sign: false }); + data.append(i32 { mag: 71, sign: true }); let extra = Option::::None(()); let bias = TensorTrait::new(shape.span(), data.span(), extra); // TEST UNQUANTIZED let result = NNTrait::linear(inputs, weights, bias, false).data; assert( - *result.at(0_usize).mag == 5541_u32 && *result.at(0_usize).sign == false, + *result.at(0_usize).mag == 5541 && *result.at(0_usize).sign == false, 'result[0] = 5541' ); assert( - *result.at(1_usize).mag == 260_u32 && *result.at(1_usize).sign == true, + *result.at(1_usize).mag == 260 && *result.at(1_usize).sign == true, 'result[1] = -260' ); // TEST QUANTIZED let result = NNTrait::linear(inputs, weights, bias, true).data; assert( - *result.at(0_usize).mag == 127_u32 && *result.at(0_usize).sign == false, + *result.at(0_usize).mag == 127 && *result.at(0_usize).sign == false, 'result[0] = 127' ); assert( - *result.at(1_usize).mag == 6_u32 && *result.at(1_usize).sign == true, 'result[1] = -6' + *result.at(1_usize).mag == 6 && *result.at(1_usize).sign == true, 'result[1] = -6' ); } diff --git a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo index 5daba51d2..3621306df 100644 --- a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo @@ -15,10 +15,10 @@ fn relu_i32_test() { shape.append(2); let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(1_u32, false); - let val_2 = IntegerTrait::new(2_u32, false); - let val_3 = IntegerTrait::new(1_u32, true); - let val_4 = IntegerTrait::new(2_u32, true); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); data.append(val_1); data.append(val_2); @@ -33,10 +33,10 @@ fn relu_i32_test() { let mut result = NNTrait::relu(@tensor, threshold); let data_0 = *result.data.at(0); - assert(data_0.mag == 1_u32, 'result[0] == 1'); + assert(data_0.mag == 1, 'result[0] == 1'); assert(data_0.sign == false, 'result[0] == 1'); let data_3 = *result.data.at(3); - assert(data_3.mag == 0_u32, 'result[3] == 0'); + assert(data_3.mag == 0, 'result[3] == 0'); assert(data_3.sign == false, 'result[3] == 0'); } diff --git a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo index c95d803e1..9cd4d5274 100644 --- a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo @@ -15,10 +15,10 @@ fn relu_u32_test() { shape.append(2); let mut data = ArrayTrait::::new(); - let val_1 = 1_u32; - let val_2 = 2_u32; - let val_3 = 3_u32; - let val_4 = 4_u32; + let val_1 = 1; + let val_2 = 2; + let val_3 = 3; + let val_4 = 4; data.append(val_1); data.append(val_2); @@ -28,7 +28,7 @@ fn relu_u32_test() { let extra = Option::::None(()); let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); - let threshold = 3_u32; + let threshold = 3; let mut result = NNTrait::relu(@tensor, threshold); let data_0 = *result.data.at(0); diff --git a/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo b/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo index 9cd5ac464..928c08074 100644 --- a/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo +++ b/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo @@ -19,10 +19,10 @@ fn sigmoid_i32_test() { shape.append(2); let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(0_u32, false); - let val_2 = IntegerTrait::new(1_u32, false); - let val_3 = IntegerTrait::new(2_u32, true); - let val_4 = IntegerTrait::new(254_u32, false); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(254, false); data.append(val_1); data.append(val_2); diff --git a/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo b/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo index 47c3c9119..cffc26fd8 100644 --- a/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo +++ b/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo @@ -17,10 +17,10 @@ fn sigmoid_u32_test() { shape.append(2); let mut data = ArrayTrait::::new(); - let val_1 = 0_u32; - let val_2 = 1_u32; - let val_3 = 2_u32; - let val_4 = 254_u32; + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 254; data.append(val_1); data.append(val_2); diff --git a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo index 372e094ec..f54e206b8 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo @@ -18,10 +18,10 @@ fn softplus_i32_test() { shape.append(2); let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(0_u32, false); - let val_2 = IntegerTrait::new(1_u32, false); - let val_3 = IntegerTrait::new(2_u32, true); - let val_4 = IntegerTrait::new(3_u32, true); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); data.append(val_1); data.append(val_2); diff --git a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo index a93b6ca1b..9da2bb101 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo @@ -20,10 +20,10 @@ fn softplus_u32_test() { shape.append(2); let mut data = ArrayTrait::::new(); - let val_1 = 0_u32; - let val_2 = 1_u32; - let val_3 = 2_u32; - let val_4 = 3_u32; + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; data.append(val_1); data.append(val_2); diff --git a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo index 97dca3688..5ece23df6 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo @@ -17,10 +17,10 @@ fn softsign_i32_test() { shape.append(2); let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(0_u32, false); - let val_2 = IntegerTrait::new(1_u32, false); - let val_3 = IntegerTrait::new(2_u32, true); - let val_4 = IntegerTrait::new(3_u32, true); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); data.append(val_1); data.append(val_2); diff --git a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo index 18423a1b5..a5158dbd3 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo @@ -21,10 +21,10 @@ fn softsign_u32_test() { shape.append(2); let mut data = ArrayTrait::::new(); - let val_1 = 0_u32; - let val_2 = 1_u32; - let val_3 = 2_u32; - let val_4 = 3_u32; + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; data.append(val_1); data.append(val_2); diff --git a/src/tests/operators/tensor/helpers/helpers_i32.cairo b/src/tests/operators/tensor/helpers/helpers_i32.cairo index 3a8dce18b..72d009a00 100644 --- a/src/tests/operators/tensor/helpers/helpers_i32.cairo +++ b/src/tests/operators/tensor/helpers/helpers_i32.cairo @@ -12,9 +12,9 @@ fn i32_tensor_1x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -30,10 +30,10 @@ fn i32_tensor_2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -47,15 +47,15 @@ fn i32_tensor_3x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); - data.append(IntegerTrait::new(6_u32, false)); - data.append(IntegerTrait::new(7_u32, false)); - data.append(IntegerTrait::new(8_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(4, false)); + data.append(IntegerTrait::new(5, false)); + data.append(IntegerTrait::new(6, false)); + data.append(IntegerTrait::new(7, false)); + data.append(IntegerTrait::new(8, false)); let extra = Option::::None(()); @@ -70,12 +70,12 @@ fn i32_tensor_3x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(4, false)); + data.append(IntegerTrait::new(5, false)); let extra = Option::::None(()); @@ -90,9 +90,9 @@ fn i32_tensor_3x1_helper() -> Tensor { sizes.append(1); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); let extra = Option::::None(()); @@ -107,12 +107,12 @@ fn i32_tensor_2x3_helper() -> Tensor { sizes.append(3); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(4, false)); + data.append(IntegerTrait::new(5, false)); let extra = Option::::None(()); @@ -130,14 +130,14 @@ fn i32_tensor_2x2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); - data.append(IntegerTrait::new(6_u32, false)); - data.append(IntegerTrait::new(7_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(4, false)); + data.append(IntegerTrait::new(5, false)); + data.append(IntegerTrait::new(6, false)); + data.append(IntegerTrait::new(7, false)); let extra = Option::::None(()); @@ -153,18 +153,18 @@ fn i32_tensor_3x2x2_helper() -> Tensor { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); - data.append(IntegerTrait::new(3_u32, false)); - data.append(IntegerTrait::new(4_u32, false)); - data.append(IntegerTrait::new(5_u32, false)); - data.append(IntegerTrait::new(6_u32, false)); - data.append(IntegerTrait::new(7_u32, false)); - data.append(IntegerTrait::new(8_u32, false)); - data.append(IntegerTrait::new(9_u32, false)); - data.append(IntegerTrait::new(10_u32, false)); - data.append(IntegerTrait::new(11_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(4, false)); + data.append(IntegerTrait::new(5, false)); + data.append(IntegerTrait::new(6, false)); + data.append(IntegerTrait::new(7, false)); + data.append(IntegerTrait::new(8, false)); + data.append(IntegerTrait::new(9, false)); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(11, false)); let extra = Option::::None(()); diff --git a/src/tests/operators/tensor/tensor_test.cairo b/src/tests/operators/tensor/tensor_test.cairo index d642185e2..9596bb48f 100644 --- a/src/tests/operators/tensor/tensor_test.cairo +++ b/src/tests/operators/tensor/tensor_test.cairo @@ -21,9 +21,9 @@ fn wrong_shape_tensor_test() { sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); - data.append(IntegerTrait::new(2_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); let extra = Option::::None(()); @@ -42,7 +42,7 @@ fn at_tensor_test() { let result = tensor.at(indices.span()).mag; - assert(result == 3_u32, 'result[3] = 3'); + assert(result == 3, 'result[3] = 3'); } #[test] @@ -151,14 +151,14 @@ fn add_tensor() { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 2_u32, 'result[1] = 2'); - assert(*result.at(2).mag == 4_u32, 'result[2] = 4'); - assert(*result.at(3).mag == 6_u32, 'result[3] = 6'); - assert(*result.at(4).mag == 8_u32, 'result[4] = 8'); - assert(*result.at(5).mag == 10_u32, 'result[5] = 10'); - assert(*result.at(6).mag == 12_u32, 'result[6] = 12'); - assert(*result.at(7).mag == 14_u32, 'result[7] = 14'); + assert(*result.at(0).mag == 0, 'result[0] = 0'); + assert(*result.at(1).mag == 2, 'result[1] = 2'); + assert(*result.at(2).mag == 4, 'result[2] = 4'); + assert(*result.at(3).mag == 6, 'result[3] = 6'); + assert(*result.at(4).mag == 8, 'result[4] = 8'); + assert(*result.at(5).mag == 10, 'result[5] = 10'); + assert(*result.at(6).mag == 12, 'result[6] = 12'); + assert(*result.at(7).mag == 14, 'result[7] = 14'); // broadcast operation @@ -167,63 +167,63 @@ fn add_tensor() { sizes.append(2); sizes.append(1); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10_u32, false)); - data.append(IntegerTrait::new(100_u32, false)); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); let extra = Option::::None(()); let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); let result = (tensor_1 + tensor_2).data; - assert(*result.at(0).mag == 10_u32, 'result[0] = 10'); - assert(*result.at(1).mag == 11_u32, 'result[1] = 11'); - assert(*result.at(2).mag == 102_u32, 'result[2] = 102'); - assert(*result.at(3).mag == 103_u32, 'result[3] = 103'); - assert(*result.at(4).mag == 14_u32, 'result[4] = 14'); - assert(*result.at(5).mag == 15_u32, 'result[5] = 15'); - assert(*result.at(6).mag == 106_u32, 'result[6] = 106'); - assert(*result.at(7).mag == 107_u32, 'result[7] = 107'); + assert(*result.at(0).mag == 10, 'result[0] = 10'); + assert(*result.at(1).mag == 11, 'result[1] = 11'); + assert(*result.at(2).mag == 102, 'result[2] = 102'); + assert(*result.at(3).mag == 103, 'result[3] = 103'); + assert(*result.at(4).mag == 14, 'result[4] = 14'); + assert(*result.at(5).mag == 15, 'result[5] = 15'); + assert(*result.at(6).mag == 106, 'result[6] = 106'); + assert(*result.at(7).mag == 107, 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(2); sizes.append(1); sizes.append(1); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10_u32, false)); - data.append(IntegerTrait::new(100_u32, false)); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); let extra = Option::::None(()); let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); let result = (tensor_1 + tensor_2).data; - assert(*result.at(0).mag == 10_u32, 'result[0] = 10'); - assert(*result.at(1).mag == 11_u32, 'result[1] = 11'); - assert(*result.at(2).mag == 12_u32, 'result[2] = 12'); - assert(*result.at(3).mag == 13_u32, 'result[3] = 13'); - assert(*result.at(4).mag == 104_u32, 'result[4] = 104'); - assert(*result.at(5).mag == 105_u32, 'result[5] = 105'); - assert(*result.at(6).mag == 106_u32, 'result[6] = 106'); - assert(*result.at(7).mag == 107_u32, 'result[7] = 107'); + assert(*result.at(0).mag == 10, 'result[0] = 10'); + assert(*result.at(1).mag == 11, 'result[1] = 11'); + assert(*result.at(2).mag == 12, 'result[2] = 12'); + assert(*result.at(3).mag == 13, 'result[3] = 13'); + assert(*result.at(4).mag == 104, 'result[4] = 104'); + assert(*result.at(5).mag == 105, 'result[5] = 105'); + assert(*result.at(6).mag == 106, 'result[6] = 106'); + assert(*result.at(7).mag == 107, 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(1); sizes.append(1); sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10_u32, false)); - data.append(IntegerTrait::new(100_u32, false)); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); let extra = Option::::None(()); let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); let result = (tensor_1 + tensor_2).data; - assert(*result.at(0).mag == 10_u32, 'result[0] = 10'); - assert(*result.at(1).mag == 101_u32, 'result[1] = 101'); - assert(*result.at(2).mag == 12_u32, 'result[2] = 12'); - assert(*result.at(3).mag == 103_u32, 'result[3] = 103'); - assert(*result.at(4).mag == 14_u32, 'result[4] = 14'); - assert(*result.at(5).mag == 105_u32, 'result[5] = 105'); - assert(*result.at(6).mag == 16_u32, 'result[6] = 16'); - assert(*result.at(7).mag == 107_u32, 'result[7] = 107'); + assert(*result.at(0).mag == 10, 'result[0] = 10'); + assert(*result.at(1).mag == 101, 'result[1] = 101'); + assert(*result.at(2).mag == 12, 'result[2] = 12'); + assert(*result.at(3).mag == 103, 'result[3] = 103'); + assert(*result.at(4).mag == 14, 'result[4] = 14'); + assert(*result.at(5).mag == 105, 'result[5] = 105'); + assert(*result.at(6).mag == 16, 'result[6] = 16'); + assert(*result.at(7).mag == 107, 'result[7] = 107'); } #[test] @@ -234,14 +234,14 @@ fn sub_tensor() { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 0_u32, 'result[1] = 0'); - assert(*result.at(2).mag == 0_u32, 'result[2] = 0'); - assert(*result.at(3).mag == 0_u32, 'result[3] = 0'); - assert(*result.at(4).mag == 0_u32, 'result[4] = 0'); - assert(*result.at(5).mag == 0_u32, 'result[5] = 0'); - assert(*result.at(6).mag == 0_u32, 'result[6] = 0'); - assert(*result.at(7).mag == 0_u32, 'result[7] = 0'); + assert(*result.at(0).mag == 0, 'result[0] = 0'); + assert(*result.at(1).mag == 0, 'result[1] = 0'); + assert(*result.at(2).mag == 0, 'result[2] = 0'); + assert(*result.at(3).mag == 0, 'result[3] = 0'); + assert(*result.at(4).mag == 0, 'result[4] = 0'); + assert(*result.at(5).mag == 0, 'result[5] = 0'); + assert(*result.at(6).mag == 0, 'result[6] = 0'); + assert(*result.at(7).mag == 0, 'result[7] = 0'); // broadcast operation @@ -250,21 +250,21 @@ fn sub_tensor() { sizes.append(2); sizes.append(1); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0_u32, false)); - data.append(IntegerTrait::new(1_u32, false)); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); let extra = Option::::None(()); let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); let result = (tensor_1 - tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 1_u32, 'result[1] = 1'); - assert(*result.at(2).mag == 1_u32, 'result[2] = 1'); - assert(*result.at(3).mag == 2_u32, 'result[3] = 2'); - assert(*result.at(4).mag == 4_u32, 'result[4] = 4'); - assert(*result.at(5).mag == 5_u32, 'result[5] = 5'); - assert(*result.at(6).mag == 5_u32, 'result[6] = 5'); - assert(*result.at(7).mag == 6_u32, 'result[7] = 6'); + assert(*result.at(0).mag == 0, 'result[0] = 0'); + assert(*result.at(1).mag == 1, 'result[1] = 1'); + assert(*result.at(2).mag == 1, 'result[2] = 1'); + assert(*result.at(3).mag == 2, 'result[3] = 2'); + assert(*result.at(4).mag == 4, 'result[4] = 4'); + assert(*result.at(5).mag == 5, 'result[5] = 5'); + assert(*result.at(6).mag == 5, 'result[6] = 5'); + assert(*result.at(7).mag == 6, 'result[7] = 6'); } #[test] @@ -275,14 +275,14 @@ fn mul_tensor() { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 1_u32, 'result[1] = 1'); - assert(*result.at(2).mag == 4_u32, 'result[2] = 4'); - assert(*result.at(3).mag == 9_u32, 'result[3] = 9'); - assert(*result.at(4).mag == 16_u32, 'result[4] = 16'); - assert(*result.at(5).mag == 25_u32, 'result[5] = 25'); - assert(*result.at(6).mag == 36_u32, 'result[6] = 36'); - assert(*result.at(7).mag == 49_u32, 'result[7] = 49'); + assert(*result.at(0).mag == 0, 'result[0] = 0'); + assert(*result.at(1).mag == 1, 'result[1] = 1'); + assert(*result.at(2).mag == 4, 'result[2] = 4'); + assert(*result.at(3).mag == 9, 'result[3] = 9'); + assert(*result.at(4).mag == 16, 'result[4] = 16'); + assert(*result.at(5).mag == 25, 'result[5] = 25'); + assert(*result.at(6).mag == 36, 'result[6] = 36'); + assert(*result.at(7).mag == 49, 'result[7] = 49'); // broadcast operation @@ -291,21 +291,21 @@ fn mul_tensor() { sizes.append(2); sizes.append(1); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10_u32, false)); - data.append(IntegerTrait::new(100_u32, false)); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); let extra = Option::::None(()); let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); let result = (tensor_1 * tensor_2).data; - assert(*result.at(0).mag == 0_u32, 'result[0] = 0'); - assert(*result.at(1).mag == 10_u32, 'result[1] = 10'); - assert(*result.at(2).mag == 200_u32, 'result[2] = 200'); - assert(*result.at(3).mag == 300_u32, 'result[3] = 300'); - assert(*result.at(4).mag == 40_u32, 'result[4] = 40'); - assert(*result.at(5).mag == 50_u32, 'result[5] = 50'); - assert(*result.at(6).mag == 600_u32, 'result[6] = 600'); - assert(*result.at(7).mag == 700_u32, 'result[7] = 700'); + assert(*result.at(0).mag == 0, 'result[0] = 0'); + assert(*result.at(1).mag == 10, 'result[1] = 10'); + assert(*result.at(2).mag == 200, 'result[2] = 200'); + assert(*result.at(3).mag == 300, 'result[3] = 300'); + assert(*result.at(4).mag == 40, 'result[4] = 40'); + assert(*result.at(5).mag == 50, 'result[5] = 50'); + assert(*result.at(6).mag == 600, 'result[6] = 600'); + assert(*result.at(7).mag == 700, 'result[7] = 700'); } #[test] @@ -316,14 +316,14 @@ fn div_tensor() { sizes.append(2); sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(100_u32, false)); - data.append(IntegerTrait::new(200_u32, false)); - data.append(IntegerTrait::new(300_u32, false)); - data.append(IntegerTrait::new(400_u32, false)); - data.append(IntegerTrait::new(500_u32, false)); - data.append(IntegerTrait::new(600_u32, false)); - data.append(IntegerTrait::new(700_u32, false)); - data.append(IntegerTrait::new(800_u32, false)); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(200, false)); + data.append(IntegerTrait::new(300, false)); + data.append(IntegerTrait::new(400, false)); + data.append(IntegerTrait::new(500, false)); + data.append(IntegerTrait::new(600, false)); + data.append(IntegerTrait::new(700, false)); + data.append(IntegerTrait::new(800, false)); let extra = Option::::None(()); let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); @@ -332,27 +332,27 @@ fn div_tensor() { sizes.append(2); sizes.append(2); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(100_u32, false)); - data.append(IntegerTrait::new(200_u32, false)); - data.append(IntegerTrait::new(300_u32, false)); - data.append(IntegerTrait::new(400_u32, false)); - data.append(IntegerTrait::new(500_u32, false)); - data.append(IntegerTrait::new(600_u32, false)); - data.append(IntegerTrait::new(700_u32, false)); - data.append(IntegerTrait::new(800_u32, false)); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(200, false)); + data.append(IntegerTrait::new(300, false)); + data.append(IntegerTrait::new(400, false)); + data.append(IntegerTrait::new(500, false)); + data.append(IntegerTrait::new(600, false)); + data.append(IntegerTrait::new(700, false)); + data.append(IntegerTrait::new(800, false)); let extra = Option::::None(()); let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); let result = (tensor_1 / tensor_2).data; - assert(*result.at(0).mag == 1_u32, 'result[0] = 1'); - assert(*result.at(1).mag == 1_u32, 'result[1] = 1'); - assert(*result.at(2).mag == 1_u32, 'result[2] = 1'); - assert(*result.at(3).mag == 1_u32, 'result[3] = 1'); - assert(*result.at(4).mag == 1_u32, 'result[4] = 1'); - assert(*result.at(5).mag == 1_u32, 'result[5] = 1'); - assert(*result.at(6).mag == 1_u32, 'result[6] = 1'); - assert(*result.at(7).mag == 1_u32, 'result[7] = 1'); + assert(*result.at(0).mag == 1, 'result[0] = 1'); + assert(*result.at(1).mag == 1, 'result[1] = 1'); + assert(*result.at(2).mag == 1, 'result[2] = 1'); + assert(*result.at(3).mag == 1, 'result[3] = 1'); + assert(*result.at(4).mag == 1, 'result[4] = 1'); + assert(*result.at(5).mag == 1, 'result[5] = 1'); + assert(*result.at(6).mag == 1, 'result[6] = 1'); + assert(*result.at(7).mag == 1, 'result[7] = 1'); // broadcast operation @@ -361,21 +361,21 @@ fn div_tensor() { sizes.append(2); sizes.append(1); let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10_u32, false)); - data.append(IntegerTrait::new(100_u32, false)); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); let extra = Option::::None(()); let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); let result = (tensor_1 / tensor_2).data; - assert(*result.at(0).mag == 10_u32, 'result[0] = 10'); - assert(*result.at(1).mag == 20_u32, 'result[1] = 20'); - assert(*result.at(2).mag == 3_u32, 'result[2] = 3'); - assert(*result.at(3).mag == 4_u32, 'result[3] = 4'); - assert(*result.at(4).mag == 50_u32, 'result[4] = 50'); - assert(*result.at(5).mag == 60_u32, 'result[5] = 60'); - assert(*result.at(6).mag == 7_u32, 'result[6] = 7'); - assert(*result.at(7).mag == 8_u32, 'result[7] = 8'); + assert(*result.at(0).mag == 10, 'result[0] = 10'); + assert(*result.at(1).mag == 20, 'result[1] = 20'); + assert(*result.at(2).mag == 3, 'result[2] = 3'); + assert(*result.at(3).mag == 4, 'result[3] = 4'); + assert(*result.at(4).mag == 50, 'result[4] = 50'); + assert(*result.at(5).mag == 60, 'result[5] = 60'); + assert(*result.at(6).mag == 7, 'result[6] = 7'); + assert(*result.at(7).mag == 8, 'result[7] = 8'); } #[test] diff --git a/src/tests/performance/quantization_test.cairo b/src/tests/performance/quantization_test.cairo index 584dfd444..a6c257a07 100644 --- a/src/tests/performance/quantization_test.cairo +++ b/src/tests/performance/quantization_test.cairo @@ -19,34 +19,34 @@ fn quantize_linear_test() { shape.append(2); let mut data = ArrayTrait::::new(); - data.append(IntegerTrait::new(30523_u32, true)); - data.append(IntegerTrait::new(24327_u32, false)); - data.append(IntegerTrait::new(12288_u32, true)); - data.append(IntegerTrait::new(29837_u32, false)); - data.append(IntegerTrait::new(19345_u32, true)); - data.append(IntegerTrait::new(15416_u32, false)); + data.append(IntegerTrait::new(30523, true)); + data.append(IntegerTrait::new(24327, false)); + data.append(IntegerTrait::new(12288, true)); + data.append(IntegerTrait::new(29837, false)); + data.append(IntegerTrait::new(19345, true)); + data.append(IntegerTrait::new(15416, false)); let extra = Option::::None(()); let tensor = TensorTrait::new(shape.span(), data.span(), extra); let mut res = PerfomanceTrait::quantize_linear(@tensor); - assert(*res.data.at(0_usize).mag == 127_u32, '*result[0] == -127'); + assert(*res.data.at(0_usize).mag == 127, '*result[0] == -127'); assert(*res.data.at(0_usize).sign == true, '*result[0] -> negative'); - assert(*res.data.at(1_usize).mag == 101_u32, '*result[1] == 101'); + assert(*res.data.at(1_usize).mag == 101, '*result[1] == 101'); assert(*res.data.at(1_usize).sign == false, '*result[1] -> positive'); - assert(*res.data.at(2_usize).mag == 51_u32, '*result[2] == -51'); + assert(*res.data.at(2_usize).mag == 51, '*result[2] == -51'); assert(*res.data.at(2_usize).sign == true, '*result[2] -> negative'); - assert(*res.data.at(3_usize).mag == 124_u32, '*result[3] == 124'); + assert(*res.data.at(3_usize).mag == 124, '*result[3] == 124'); assert(*res.data.at(3_usize).sign == false, '*result[3] -> positive'); - assert(*res.data.at(4_usize).mag == 80_u32, '*result[4] == -80'); + assert(*res.data.at(4_usize).mag == 80, '*result[4] == -80'); assert(*res.data.at(4_usize).sign == true, '*result[4] -> negative'); - assert(*res.data.at(5_usize).mag == 64_u32, '*result[5] == 64'); + assert(*res.data.at(5_usize).mag == 64, '*result[5] == 64'); assert(*res.data.at(5_usize).sign == false, '*result[5] -> positive'); } From 0509b9c8b3f72151f97a187bc0e99974125586f1 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 20:32:19 +0300 Subject: [PATCH 020/126] Update CHANGELOG.md --- docs/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index aff40fded..e3956cf25 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] - 2023-06-20 + +### Changed +- Upgrade Cairo version to v2.0.0-rc + ## [Unreleased] - 2023-06-17 ### Added From 3f3c5b2e6e86dd1edf110c8d2e2ce7f138dbfa3c Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 20:34:15 +0300 Subject: [PATCH 021/126] Update test.yaml --- .github/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1bb4ad0d7..326a89aac 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -3,7 +3,7 @@ name: Tests on: [push, pull_request] env: - ARCHIVE_LINK: https://github.com/starkware-libs/cairo/releases/download/v1.1.0/release-x86_64-unknown-linux-musl.tar.gz + ARCHIVE_LINK: https://github.com/starkware-libs/cairo/releases/download/v2.0.0-rc3/release-x86_64-unknown-linux-musl.tar.gz ARCHIVE_NAME: cairo.zip jobs: From a728e0738063e2e20e8b4bcad40227b4932b9883 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Tue, 20 Jun 2023 22:07:15 +0300 Subject: [PATCH 022/126] fix build errors --- src/tests/helpers/tensor/fixed_point/fp16x16.cairo | 4 ++-- src/tests/helpers/tensor/fixed_point/fp8x23.cairo | 4 ++-- src/tests/helpers/tensor/i32.cairo | 2 +- .../matmul/matmul_fp_test/matmul_fp16x16_test.cairo | 4 ++-- .../linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo | 4 ++-- src/tests/operators/linalg/matmul/matmul_u32_test.cairo | 2 +- .../operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo | 4 ++-- .../operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo | 4 ++-- .../math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo | 4 ++-- .../math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo | 4 ++-- .../math/equal/equal_fp_test/equal_fp16x16_test.cairo | 4 ++-- .../math/equal/equal_fp_test/equal_fp8x23_test.cairo | 4 ++-- src/tests/operators/math/exp_test.cairo | 2 +- src/tests/operators/math/greater/greater_fp_test.cairo | 3 +-- .../greater/greater_fp_test/greater_fp16x16_test.cairo | 4 ++-- .../greater/greater_fp_test/greater_fp8x23_test.cairo | 4 ++-- src/tests/operators/math/ln_test.cairo | 2 +- .../nn/functional/leaky_relu/leaky_relu_i32_test.cairo | 8 ++++---- .../nn/functional/logsoftmax/logsoftmax_test.cairo | 2 +- .../operators/nn/functional/softmax/softmax_test.cairo | 2 +- .../nn/functional/softplus/softplus_i32_test.cairo | 2 +- .../nn/functional/softsign/softsign_i32_test.cairo | 2 +- 22 files changed, 37 insertions(+), 38 deletions(-) diff --git a/src/tests/helpers/tensor/fixed_point/fp16x16.cairo b/src/tests/helpers/tensor/fixed_point/fp16x16.cairo index 279f6df41..c07b396c7 100644 --- a/src/tests/helpers/tensor/fixed_point/fp16x16.cairo +++ b/src/tests/helpers/tensor/fixed_point/fp16x16.cairo @@ -1,8 +1,8 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; -use orion::numbers::fixed_point::implementations::impl_16x16; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; // 1D diff --git a/src/tests/helpers/tensor/fixed_point/fp8x23.cairo b/src/tests/helpers/tensor/fixed_point/fp8x23.cairo index 2b978cd46..9d817f833 100644 --- a/src/tests/helpers/tensor/fixed_point/fp8x23.cairo +++ b/src/tests/helpers/tensor/fixed_point/fp8x23.cairo @@ -1,8 +1,8 @@ use array::ArrayTrait; use array::SpanTrait; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; // 1D diff --git a/src/tests/helpers/tensor/i32.cairo b/src/tests/helpers/tensor/i32.cairo index b01ce5a3e..4f29cbf4f 100644 --- a/src/tests/helpers/tensor/i32.cairo +++ b/src/tests/helpers/tensor/i32.cairo @@ -3,7 +3,7 @@ use array::SpanTrait; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::impl_tensor_i32; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; // 1D diff --git a/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo b/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo index fa6e7a843..90377bde8 100644 --- a/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo +++ b/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo @@ -2,9 +2,9 @@ use array::ArrayTrait; use array::SpanTrait; use traits::Into; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; use orion::numbers::fixed_point::core::FixedTrait; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::TensorTrait; use orion::tests::helpers::tensor::fixed_point::fp16x16::{ fp_tensor_1x3_helper, fp_tensor_2x2_helper, fp_tensor_3x3_helper diff --git a/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo b/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo index 01e507caf..fe97ce874 100644 --- a/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo +++ b/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo @@ -2,9 +2,9 @@ use array::ArrayTrait; use array::SpanTrait; use traits::Into; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; use orion::numbers::fixed_point::core::FixedTrait; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::TensorTrait; use orion::tests::helpers::tensor::fixed_point::fp8x23::{ fp_tensor_1x3_helper, fp_tensor_2x2_helper, fp_tensor_3x3_helper diff --git a/src/tests/operators/linalg/matmul/matmul_u32_test.cairo b/src/tests/operators/linalg/matmul/matmul_u32_test.cairo index 62196a0c9..216e26a82 100644 --- a/src/tests/operators/linalg/matmul/matmul_u32_test.cairo +++ b/src/tests/operators/linalg/matmul/matmul_u32_test.cairo @@ -2,7 +2,7 @@ use array::ArrayTrait; use array::SpanTrait; use traits::Into; -use orion::operators::tensor::implementations::impl_tensor_u32; +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; use orion::operators::tensor::core::TensorTrait; use orion::tests::helpers::tensor::u32::{ u32_tensor_1x3_helper, u32_tensor_2x2_helper, u32_tensor_3x3_helper diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo b/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo index a22ca9bd3..57ae325cf 100644 --- a/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo @@ -2,13 +2,13 @@ use array::SpanTrait; use array::ArrayTrait; use core::traits::Into; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::tests::helpers::tensor::fixed_point::fp16x16::{ fp_tensor_1x3_neg_helper, fp_tensor_2x2_neg_helper, fp_tensor_2x2x2_neg_helper }; use orion::numbers::fixed_point::core::{FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; // ===== 1D ===== // diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo b/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo index 1900f6018..a5a61bd1a 100644 --- a/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo @@ -2,13 +2,13 @@ use array::SpanTrait; use array::ArrayTrait; use core::traits::Into; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::tests::helpers::tensor::fixed_point::fp8x23::{ fp_tensor_1x3_neg_helper, fp_tensor_2x2_neg_helper, fp_tensor_2x2x2_neg_helper }; use orion::numbers::fixed_point::core::{FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; // ===== 1D ===== // diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo index 5879d7226..6cdd4fc9c 100644 --- a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo +++ b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo @@ -1,10 +1,10 @@ use array::SpanTrait; use array::ArrayTrait; use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; // ===== 1D ===== // diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo index a91c2894f..71c623c16 100644 --- a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo +++ b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo @@ -1,10 +1,10 @@ use array::SpanTrait; use array::ArrayTrait; use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; // ===== 1D ===== // diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo b/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo index af03a260b..6b8144d49 100644 --- a/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo +++ b/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo @@ -1,10 +1,10 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; // ===== 1D ===== // diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo b/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo index a2ad15dfe..95b4a3aa8 100644 --- a/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo +++ b/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo @@ -1,10 +1,10 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; // ===== 1D ===== // diff --git a/src/tests/operators/math/exp_test.cairo b/src/tests/operators/math/exp_test.cairo index 2a553ebef..5952de07a 100644 --- a/src/tests/operators/math/exp_test.cairo +++ b/src/tests/operators/math/exp_test.cairo @@ -3,7 +3,7 @@ use traits::Into; use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::operators::tensor::core::{TensorTrait, }; -use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; #[test] diff --git a/src/tests/operators/math/greater/greater_fp_test.cairo b/src/tests/operators/math/greater/greater_fp_test.cairo index 8920240a6..10e5501a2 100644 --- a/src/tests/operators/math/greater/greater_fp_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test.cairo @@ -1,3 +1,2 @@ mod greater_fp8x23_test; -// TODO: The following panics with "Failed setting up runner. - Failed calculating gas usage" -// mod greater_fp16x16_test; +mod greater_fp16x16_test; diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo b/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo index 32139941e..ad69703de 100644 --- a/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo @@ -1,10 +1,10 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; // ===== 1D ===== // diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo b/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo index ee1b48916..ae9a42af2 100644 --- a/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo @@ -1,10 +1,10 @@ use array::SpanTrait; use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; // ===== 1D ===== // diff --git a/src/tests/operators/math/ln_test.cairo b/src/tests/operators/math/ln_test.cairo index 86fdcc67e..fcd34d77b 100644 --- a/src/tests/operators/math/ln_test.cairo +++ b/src/tests/operators/math/ln_test.cairo @@ -4,7 +4,7 @@ use array::ArrayTrait; use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::tests::operators::tensor::helpers::helpers_i32::i32_tensor_2x2_helper; +use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo index 059251360..8eb08aa33 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo @@ -2,15 +2,15 @@ use core::option::OptionTrait; use array::ArrayTrait; use array::SpanTrait; use traits::Into; +use core::integer::NumericLiteral; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::nn::core::{NNTrait}; +use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; - -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE}; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE, FP8x23Into}; #[test] #[available_gas(2000000)] @@ -43,7 +43,7 @@ fn leaky_relu_i32_test() { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 - assert((*result.data.at(3)).into() == - 1677722, 'result[3] == - 1677722'); // 2 * 0.1 = - 0.2 + assert((*result.data.at(3)).into() == -1677722, 'result[3] == - 1677722'); // 2 * 0.1 = - 0.2 assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); } diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo index 72da585c1..abf545b34 100644 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo @@ -5,7 +5,7 @@ use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32::NN_i32; diff --git a/src/tests/operators/nn/functional/softmax/softmax_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_test.cairo index 590498534..d40fad2d1 100644 --- a/src/tests/operators/nn/functional/softmax/softmax_test.cairo +++ b/src/tests/operators/nn/functional/softmax/softmax_test.cairo @@ -5,7 +5,7 @@ use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; use orion::numbers::fixed_point::core::FixedImpl; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32::NN_i32; diff --git a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo index 664cf76a0..0b3ac1cde 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo @@ -9,7 +9,7 @@ use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use orion::numbers::fixed_point::core::FixedImpl; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; #[test] #[available_gas(50000000)] diff --git a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo index 752d3b38c..d7c8417a8 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo @@ -9,7 +9,7 @@ use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; use orion::operators::nn::core::NNTrait; use orion::operators::nn::implementations::impl_nn_i32::NN_i32; use orion::numbers::fixed_point::core::FixedImpl; -use orion::numbers::fixed_point::implementations::impl_8x23; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; #[test] #[available_gas(2000000)] From cbf14fea9567509cdb5e3f69f21ac92a8983fea1 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 09:59:32 +0300 Subject: [PATCH 023/126] encapsulate tests in modules for each dimension --- .../abs/abs_fp_test/abs_fp16x16_test.cairo | 104 ++-- .../abs/abs_fp_test/abs_fp8x23_test.cairo | 103 ++-- .../operators/math/abs/abs_i32_test.cairo | 110 ++-- .../operators/math/abs/abs_u32_test.cairo | 82 ++- .../ceil/ceil_fp_test/ceil_fp16x16_test.cairo | 171 +++--- .../ceil/ceil_fp_test/ceil_fp8x23_test.cairo | 169 +++--- .../operators/math/ceil/ceil_i32_test.cairo | 118 ++-- .../operators/math/ceil/ceil_u32_test.cairo | 101 ++-- .../equal_fp_test/equal_fp16x16_test.cairo | 502 ++++++++-------- .../equal_fp_test/equal_fp8x23_test.cairo | 506 ++++++++-------- .../operators/math/equal/equal_i32_test.cairo | 498 ++++++++-------- .../operators/math/equal/equal_u32_test.cairo | 505 ++++++++-------- .../greater_fp16x16_test.cairo | 559 ++++++++--------- .../greater_fp_test/greater_fp8x23_test.cairo | 561 +++++++++--------- .../math/greater/greater_i32_test.cairo | 558 ++++++++--------- .../math/greater/greater_u32_test.cairo | 559 ++++++++--------- 16 files changed, 2791 insertions(+), 2415 deletions(-) diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo b/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo index 57ae325cf..fe91bda3a 100644 --- a/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo @@ -1,56 +1,70 @@ -use array::SpanTrait; -use array::ArrayTrait; -use core::traits::Into; - -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::tests::helpers::tensor::fixed_point::fp16x16::{ - fp_tensor_1x3_neg_helper, fp_tensor_2x2_neg_helper, fp_tensor_2x2x2_neg_helper -}; -use orion::numbers::fixed_point::core::{FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; - - // ===== 1D ===== // -#[test] -#[available_gas(2000000000)] -fn abs_1D() { - let tensor = fp_tensor_1x3_neg_helper(); - let result = tensor.abs(); - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(2000000000)] + fn tensor_abs() { + let tensor = fp_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); + } } + // ===== 2D ===== // -#[test] -#[available_gas(2000000000)] -fn abs_2D() { - let tensor = fp_tensor_2x2_neg_helper(); - let result = tensor.abs(); - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(2000000000)] + fn tensor_abs() { + let tensor = fp_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000000)] -fn abs_3D() { - let tensor = fp_tensor_2x2x2_neg_helper(); - let result = tensor.abs(); - - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); - assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); -} +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + #[test] + #[available_gas(2000000000)] + fn tensor_abs() { + let tensor = fp_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); + assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + } +} diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo b/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo index a5a61bd1a..878719c1e 100644 --- a/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo +++ b/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo @@ -1,56 +1,69 @@ -use array::SpanTrait; -use array::ArrayTrait; -use core::traits::Into; - -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::tests::helpers::tensor::fixed_point::fp8x23::{ - fp_tensor_1x3_neg_helper, fp_tensor_2x2_neg_helper, fp_tensor_2x2x2_neg_helper -}; -use orion::numbers::fixed_point::core::{FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; - - // ===== 1D ===== // -#[test] -#[available_gas(2000000000)] -fn abs_1D() { - let tensor = fp_tensor_1x3_neg_helper(); - let result = tensor.abs(); - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000000)] + fn tensor_abs() { + let tensor = fp_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); + } } // ===== 2D ===== // -#[test] -#[available_gas(2000000000)] -fn abs_2D() { - let tensor = fp_tensor_2x2_neg_helper(); - let result = tensor.abs(); - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000000)] + fn tensor_abs() { + let tensor = fp_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000000)] -fn abs_3D() { - let tensor = fp_tensor_2x2x2_neg_helper(); - let result = tensor.abs(); - - assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); - assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); -} +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_neg_helper; + use orion::numbers::fixed_point::core::{FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + #[test] + #[available_gas(2000000000)] + fn tensor_abs() { + let tensor = fp_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.data[6] == FixedTrait::new_unscaled(6, false), 'result[6] = 6'); + assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + } +} diff --git a/src/tests/operators/math/abs/abs_i32_test.cairo b/src/tests/operators/math/abs/abs_i32_test.cairo index f2c4173df..4a371ec4a 100644 --- a/src/tests/operators/math/abs/abs_i32_test.cairo +++ b/src/tests/operators/math/abs/abs_i32_test.cairo @@ -1,44 +1,68 @@ -use array::SpanTrait; -use array::ArrayTrait; -use core::traits::Into; - -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::tests::helpers::tensor::i32::i32_tensor_1x3_neg_helper; -use orion::tests::helpers::tensor::i32::i32_tensor_2x2_neg_helper; -use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_neg_helper; - - -#[test] -#[available_gas(2000000000000000000)] -fn tensor_abs() { - // ===== 1D ===== // - - let tensor = i32_tensor_1x3_neg_helper(); - let result = tensor.abs(); - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 1, 'result[1] = 1'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - - // ===== 2D ===== // - - let tensor = i32_tensor_2x2_neg_helper(); - let result = tensor.abs(); - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 1, 'result[1] = 1'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - assert((*result.data[3]).into() == 3, 'result[3] = 3'); - - // ===== 3D ===== // - - let tensor = i32_tensor_2x2x2_neg_helper(); - let result = tensor.abs(); - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 1, 'result[1] = 1'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - assert((*result.data[3]).into() == 3, 'result[3] = 3'); - assert((*result.data[4]).into() == 4, 'result[4] = 4'); - assert((*result.data[5]).into() == 5, 'result[5] = 5'); - assert((*result.data[6]).into() == 6, 'result[6] = 6'); - assert((*result.data[7]).into() == 7, 'result[7] = 7'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_neg_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_abs() { + let tensor = i32_tensor_1x3_neg_helper(); + let result = tensor.abs(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_neg_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_abs() { + let tensor = i32_tensor_2x2_neg_helper(); + let result = tensor.abs(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_neg_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_abs() { + let tensor = i32_tensor_2x2x2_neg_helper(); + let result = tensor.abs(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + } } diff --git a/src/tests/operators/math/abs/abs_u32_test.cairo b/src/tests/operators/math/abs/abs_u32_test.cairo index 9968c1f82..0a15b1c6e 100644 --- a/src/tests/operators/math/abs/abs_u32_test.cairo +++ b/src/tests/operators/math/abs/abs_u32_test.cairo @@ -8,43 +8,65 @@ use orion::tests::helpers::tensor::u32::{ // ===== 1D ===== // -#[test] -#[available_gas(20000000)] -fn tensor_abs_1D() { - let tensor = u32_tensor_1x3_helper(); - let result = tensor.abs(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + + #[test] + #[available_gas(20000000)] + fn tensor_abs() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + } } // ===== 2D ===== // -#[test] -#[available_gas(20000000)] -fn tensor_abs_2D() { - let tensor = u32_tensor_2x2_helper(); - let result = tensor.abs(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - assert(*result.data[3] == 3, 'result[3] = 3'); +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_abs() { + let tensor = u32_tensor_2x2_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + } } // ===== 3D ===== // -#[test] -#[available_gas(20000000)] -fn tensor_abs_3D() { - let tensor = u32_tensor_2x2x2_helper(); - let result = tensor.abs(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - assert(*result.data[3] == 3, 'result[3] = 3'); - assert(*result.data[4] == 4, 'result[4] = 4'); - assert(*result.data[5] == 5, 'result[5] = 5'); - assert(*result.data[6] == 6, 'result[6] = 6'); - assert(*result.data[7] == 7, 'result[7] = 7'); +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_abs() { + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.abs(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + assert(*result.data[4] == 4, 'result[4] = 4'); + assert(*result.data[5] == 5, 'result[5] = 5'); + assert(*result.data[6] == 6, 'result[6] = 6'); + assert(*result.data[7] == 7, 'result[7] = 7'); + } } diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo index 6cdd4fc9c..2def81007 100644 --- a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo +++ b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo @@ -1,90 +1,113 @@ -use array::SpanTrait; -use array::ArrayTrait; -use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; - // ===== 1D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_ceil_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(4); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(234, false)); // 0.00357627868 - arr.append(FixedTrait::new(786431, false)); // 11.9999947548 - arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(2000000)] + fn tensor_ceil() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } } + // ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_ceil_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(234, false)); // 0.00357627868 - arr.append(FixedTrait::new(786431, false)); // 11.9999947548 - arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(2000000)] + fn tensor_ceil() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_ceil_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(234, false)); // 0.00357627868 - arr.append(FixedTrait::new(786431, false)); // 11.9999947548 - arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 - arr.append(FixedTrait::new(32768, false)); // 0.5 - arr.append(FixedTrait::new(32768, true)); // - 0.5 - arr.append(FixedTrait::new(98304, false)); // 1.5 - arr.append(FixedTrait::new(98304, true)); // - 1.5 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + #[test] + #[available_gas(2000000)] + fn tensor_ceil() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); -} + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(234, false)); // 0.00357627868 + arr.append(FixedTrait::new(786431, false)); // 11.9999947548 + arr.append(FixedTrait::new(786431, true)); // - 11.9999947548 + arr.append(FixedTrait::new(32768, false)); // 0.5 + arr.append(FixedTrait::new(32768, true)); // - 0.5 + arr.append(FixedTrait::new(98304, false)); // 1.5 + arr.append(FixedTrait::new(98304, true)); // - 1.5 + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } +} diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo index 71c623c16..935bd0702 100644 --- a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo +++ b/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo @@ -1,90 +1,113 @@ -use array::SpanTrait; -use array::ArrayTrait; -use option::OptionTrait; -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; - // ===== 1D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_ceil_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(4); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(30000, false)); // 0.00357627868 - arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 - arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000)] + fn tensor_cei() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } } // ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_ceil_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(30000, false)); // 0.00357627868 - arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 - arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000)] + fn tensor_cei() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_ceil_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + + #[test] + #[available_gas(2000000)] + fn tensor_cei() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); - let mut arr = ArrayTrait::::new(); - arr.append(FixedTrait::new(0, false)); - arr.append(FixedTrait::new(30000, false)); // 0.00357627868 - arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 - arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 - arr.append(FixedTrait::new(4194304, false)); // 0.5 - arr.append(FixedTrait::new(4194304, true)); // - 0.5 - arr.append(FixedTrait::new(12582912, false)); // 1.5 - arr.append(FixedTrait::new(12582912, true)); // - 1.5 + let mut arr = ArrayTrait::::new(); + arr.append(FixedTrait::new(0, false)); + arr.append(FixedTrait::new(30000, false)); // 0.00357627868 + arr.append(FixedTrait::new(100663252, false)); // 11.9999947548 + arr.append(FixedTrait::new(100663252, true)); // - 11.9999947548 + arr.append(FixedTrait::new(4194304, false)); // 0.5 + arr.append(FixedTrait::new(4194304, true)); // - 0.5 + arr.append(FixedTrait::new(12582912, false)); // 1.5 + arr.append(FixedTrait::new(12582912, true)); // - 1.5 - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); - let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); - assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + let result = tensor.ceil(); + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); + assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); + } } diff --git a/src/tests/operators/math/ceil/ceil_i32_test.cairo b/src/tests/operators/math/ceil/ceil_i32_test.cairo index a22a93b63..62663720e 100644 --- a/src/tests/operators/math/ceil/ceil_i32_test.cairo +++ b/src/tests/operators/math/ceil/ceil_i32_test.cairo @@ -1,43 +1,77 @@ -use array::SpanTrait; -use array::ArrayTrait; -use core::traits::Into; - -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; -use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; -use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; - -#[test] -#[available_gas(2000000000000000000)] -fn tensor_ceil() { - // ===== 1D ===== // - - let tensor = i32_tensor_1x3_helper(); - let result = tensor.ceil(); - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 1, 'result[1] = 1'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - - // ===== 2D ===== // - - let tensor = i32_tensor_2x2_helper(); - let result = tensor.ceil(); - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 1, 'result[1] = 1'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - assert((*result.data[3]).into() == 3, 'result[3] = 3'); - - // ===== 3D ===== // - - let tensor = i32_tensor_2x2x2_helper(); - let result = tensor.ceil(); - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 1, 'result[1] = 1'); - assert((*result.data[2]).into() == 2, 'result[2] = 2'); - assert((*result.data[3]).into() == 3, 'result[3] = 3'); - assert((*result.data[4]).into() == 4, 'result[4] = 4'); - assert((*result.data[5]).into() == 5, 'result[5] = 5'); - assert((*result.data[6]).into() == 6, 'result[6] = 6'); - assert((*result.data[7]).into() == 7, 'result[7] = 7'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_ceil() { + let tensor = i32_tensor_1x3_helper(); + let result = tensor.ceil(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_ceil() { + let tensor = i32_tensor_2x2_helper(); + let result = tensor.ceil(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + } +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + + + #[test] + #[available_gas(20000000)] + fn tensor_ceil() { + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.ceil(); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + } } diff --git a/src/tests/operators/math/ceil/ceil_u32_test.cairo b/src/tests/operators/math/ceil/ceil_u32_test.cairo index 34ed349f5..ae9586d7b 100644 --- a/src/tests/operators/math/ceil/ceil_u32_test.cairo +++ b/src/tests/operators/math/ceil/ceil_u32_test.cairo @@ -1,49 +1,74 @@ -use array::SpanTrait; -use array::ArrayTrait; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::tests::helpers::tensor::u32::{ - u32_tensor_1x3_helper, u32_tensor_2x2_helper, u32_tensor_2x2x2_helper -}; - // ===== 1D ===== // -#[test] -#[available_gas(20000000)] -fn tensor_ceil_1D() { - let tensor = u32_tensor_1x3_helper(); - let result = tensor.ceil(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_ceil() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + } } + // ===== 2D ===== // -#[test] -#[available_gas(20000000)] -fn tensor_ceil_2D() { - let tensor = u32_tensor_2x2_helper(); - let result = tensor.ceil(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - assert(*result.data[3] == 3, 'result[3] = 3'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_ceil() { + let tensor = u32_tensor_2x2_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + } } + // ===== 3D ===== // -#[test] -#[available_gas(20000000)] -fn tensor_ceil_3D() { - let tensor = u32_tensor_2x2x2_helper(); - let result = tensor.ceil(); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 1, 'result[1] = 1'); - assert(*result.data[2] == 2, 'result[2] = 2'); - assert(*result.data[3] == 3, 'result[3] = 3'); - assert(*result.data[4] == 4, 'result[4] = 4'); - assert(*result.data[5] == 5, 'result[5] = 5'); - assert(*result.data[6] == 6, 'result[6] = 6'); - assert(*result.data[7] == 7, 'result[7] = 7'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_ceil() { + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.ceil(); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 2, 'result[2] = 2'); + assert(*result.data[3] == 3, 'result[3] = 3'); + assert(*result.data[4] == 4, 'result[4] = 4'); + assert(*result.data[5] == 5, 'result[5] = 5'); + assert(*result.data[6] == 6, 'result[6] = 6'); + assert(*result.data[7] == 7, 'result[7] = 7'); + } } + diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo b/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo index 6b8144d49..f5de9ca26 100644 --- a/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo +++ b/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo @@ -1,258 +1,284 @@ -use array::SpanTrait; -use array::{ArrayTrait}; +// ===== 1D ===== // -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; -// ===== 1D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); + #[test] + #[available_gas(2000000)] + fn tensor_eq() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, true)); - arr_1.append(FixedTrait::new_unscaled(2, false)); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, true)); + arr_1.append(FixedTrait::new_unscaled(2, false)); - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(2, false)); + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = Option::::None(()); - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } // ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - arr_1.append(FixedTrait::new_unscaled(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(12, false)); - arr_2.append(FixedTrait::new_unscaled(3, true)); - arr_2.append(FixedTrait::new_unscaled(4, false)); - arr_2.append(FixedTrait::new_unscaled(5, false)); - arr_2.append(FixedTrait::new_unscaled(16, false)); - arr_2.append(FixedTrait::new_unscaled(17, false)); - arr_2.append(FixedTrait::new_unscaled(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_eq_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - arr_1.append(FixedTrait::new_unscaled(8, false)); - arr_1.append(FixedTrait::new_unscaled(9, false)); - arr_1.append(FixedTrait::new_unscaled(10, false)); - arr_1.append(FixedTrait::new_unscaled(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(0, false)); - arr_2.append(FixedTrait::new_unscaled(1, false)); - arr_2.append(FixedTrait::new_unscaled(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(2000000)] + fn tensor_eq_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(12, false)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data.at(8) == 0, 'result[8] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_eq_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data.at(9) == 0, 'result[9] = 0'); + assert(*result_b.data.at(10) == 0, 'result[10] = 0'); + assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(12, false)); - arr_2.append(FixedTrait::new_unscaled(3, true)); - arr_2.append(FixedTrait::new_unscaled(4, false)); - arr_2.append(FixedTrait::new_unscaled(5, false)); - arr_2.append(FixedTrait::new_unscaled(16, false)); - arr_2.append(FixedTrait::new_unscaled(17, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(2000000)] + fn tensor_eq() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(12, false)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_eq_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_eq_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(0, false)); - arr_2.append(FixedTrait::new_unscaled(1, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo b/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo index 95b4a3aa8..79ea79852 100644 --- a/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo +++ b/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo @@ -1,258 +1,284 @@ -use array::SpanTrait; -use array::{ArrayTrait}; - -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +// ===== 1D ===== // +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; -// ===== 1D ===== // + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; -#[test] -#[available_gas(2000000)] -fn tensor_eq_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); + #[test] + #[available_gas(2000000)] + fn tensor_eq_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, true)); - arr_1.append(FixedTrait::new_unscaled(2, false)); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, true)); + arr_1.append(FixedTrait::new_unscaled(2, false)); - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(2, false)); + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = Option::::None(()); - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -// ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - arr_1.append(FixedTrait::new_unscaled(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(12, false)); - arr_2.append(FixedTrait::new_unscaled(3, true)); - arr_2.append(FixedTrait::new_unscaled(4, false)); - arr_2.append(FixedTrait::new_unscaled(5, false)); - arr_2.append(FixedTrait::new_unscaled(16, false)); - arr_2.append(FixedTrait::new_unscaled(17, false)); - arr_2.append(FixedTrait::new_unscaled(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} +// ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - arr_1.append(FixedTrait::new_unscaled(8, false)); - arr_1.append(FixedTrait::new_unscaled(9, false)); - arr_1.append(FixedTrait::new_unscaled(10, false)); - arr_1.append(FixedTrait::new_unscaled(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(0, false)); - arr_2.append(FixedTrait::new_unscaled(1, false)); - arr_2.append(FixedTrait::new_unscaled(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + + #[test] + #[available_gas(2000000)] + fn tensor_eq_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(12, false)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data.at(8) == 0, 'result[8] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_eq_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data.at(9) == 0, 'result[9] = 0'); + assert(*result_b.data.at(10) == 0, 'result[10] = 0'); + assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(12, false)); - arr_2.append(FixedTrait::new_unscaled(3, true)); - arr_2.append(FixedTrait::new_unscaled(4, false)); - arr_2.append(FixedTrait::new_unscaled(5, false)); - arr_2.append(FixedTrait::new_unscaled(16, false)); - arr_2.append(FixedTrait::new_unscaled(17, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_eq_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(0, false)); - arr_2.append(FixedTrait::new_unscaled(1, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(2000000)] + fn tensor_eq_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(12, false)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_eq_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } diff --git a/src/tests/operators/math/equal/equal_i32_test.cairo b/src/tests/operators/math/equal/equal_i32_test.cairo index 671cefe56..ce62fcf89 100644 --- a/src/tests/operators/math/equal/equal_i32_test.cairo +++ b/src/tests/operators/math/equal/equal_i32_test.cairo @@ -1,256 +1,280 @@ -use array::SpanTrait; -use array::{ArrayTrait}; +// ===== 1D ===== // -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; -// ===== 1D ===== // + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -#[test] -#[available_gas(2000000)] -fn tensor_eq_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); + #[test] + #[available_gas(2000000)] + fn tensor_eq_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, true)); - arr_1.append(IntegerTrait::new(2, false)); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, true)); + arr_1.append(IntegerTrait::new(2, false)); - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(2, false)); + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, false)); - let extra = Option::::None(()); + let extra = Option::::None(()); - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } // ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(12, false)); - arr_2.append(IntegerTrait::new(3, true)); - arr_2.append(IntegerTrait::new(4, false)); - arr_2.append(IntegerTrait::new(5, false)); - arr_2.append(IntegerTrait::new(16, false)); - arr_2.append(IntegerTrait::new(17, false)); - arr_2.append(IntegerTrait::new(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_eq_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - arr_1.append(IntegerTrait::new(9, false)); - arr_1.append(IntegerTrait::new(10, false)); - arr_1.append(IntegerTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(0, false)); - arr_2.append(IntegerTrait::new(1, false)); - arr_2.append(IntegerTrait::new(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_eq_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(12, false)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + arr_2.append(IntegerTrait::new(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data.at(8) == 0, 'result[8] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_eq_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + arr_1.append(IntegerTrait::new(9, false)); + arr_1.append(IntegerTrait::new(10, false)); + arr_1.append(IntegerTrait::new(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + arr_2.append(IntegerTrait::new(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data.at(9) == 0, 'result[9] = 0'); + assert(*result_b.data.at(10) == 0, 'result[10] = 0'); + assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(12, false)); - arr_2.append(IntegerTrait::new(3, true)); - arr_2.append(IntegerTrait::new(4, false)); - arr_2.append(IntegerTrait::new(5, false)); - arr_2.append(IntegerTrait::new(16, false)); - arr_2.append(IntegerTrait::new(17, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_eq_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(12, false)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_eq_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_eq_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(0, false)); - arr_2.append(IntegerTrait::new(1, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} diff --git a/src/tests/operators/math/equal/equal_u32_test.cairo b/src/tests/operators/math/equal/equal_u32_test.cairo index 89abce7fb..88afbd0a5 100644 --- a/src/tests/operators/math/equal/equal_u32_test.cairo +++ b/src/tests/operators/math/equal/equal_u32_test.cairo @@ -1,255 +1,276 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - // ===== 1D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10); - arr_2.append(11); - arr_2.append(2); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data[0] == 0, 'result[0] = 0'); - assert(*result.data[1] == 0, 'result[1] = 0'); - assert(*result.data[2] == 1, 'result[2] = 1'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_eq() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 1, 'result[2] = 1'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } + // ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(5); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10); - arr_2.append(11); - arr_2.append(12); - arr_2.append(13); - arr_2.append(4); - arr_2.append(5); - arr_2.append(16); - arr_2.append(17); - arr_2.append(18); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_eq() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data.at(8) == 0, 'result[8] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_eq_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data.at(9) == 0, 'result[9] = 0'); + assert(*result_b.data.at(10) == 0, 'result[10] = 0'); + assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_eq_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(5); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - arr_1.append(9); - arr_1.append(10); - arr_1.append(11); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0); - arr_2.append(1); - arr_2.append(2); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} // ===== 3D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_eq_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10_u32); - arr_2.append(11_u32); - arr_2.append(12_u32); - arr_2.append(13_u32); - arr_2.append(4_u32); - arr_2.append(5_u32); - arr_2.append(16_u32); - arr_2.append(17_u32); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - - assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_eq_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(5_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0_u32); - arr_2.append(1_u32); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_eq() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0_u32); + arr_1.append(1_u32); + arr_1.append(2_u32); + arr_1.append(3_u32); + arr_1.append(4_u32); + arr_1.append(5_u32); + arr_1.append(6_u32); + arr_1.append(7_u32); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10_u32); + arr_2.append(11_u32); + arr_2.append(12_u32); + arr_2.append(13_u32); + arr_2.append(4_u32); + arr_2.append(5_u32); + arr_2.append(16_u32); + arr_2.append(17_u32); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result = tensor_a.eq(@tensor_b); + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data.at(2) == 0, 'result[2] = 0'); + assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data.at(4) == 1, 'result[4] = 1'); + assert(*result.data.at(5) == 1, 'result[5] = 1'); + assert(*result.data.at(6) == 0, 'result[6] = 0'); + assert(*result.data.at(7) == 0, 'result[7] = 0'); + + assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_eq_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0_u32); + arr_1.append(1_u32); + arr_1.append(2_u32); + arr_1.append(3_u32); + arr_1.append(4_u32); + arr_1.append(5_u32); + arr_1.append(6_u32); + arr_1.append(7_u32); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0_u32); + arr_2.append(1_u32); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.eq(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.eq(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo b/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo index ad69703de..8556ec9e7 100644 --- a/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo @@ -1,286 +1,313 @@ -use array::SpanTrait; -use array::{ArrayTrait}; +// ===== 1D ===== // -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; -// ===== 1D ===== // + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(2, true)); + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); - let extra = Option::::None(()); + let extra = Option::::None(()); - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } // ===== 2D ===== // -#[test] -#[available_gas(200000000000)] -fn tensor_greater_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - arr_1.append(FixedTrait::new_unscaled(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(2, true)); - arr_2.append(FixedTrait::new_unscaled(3, true)); - arr_2.append(FixedTrait::new_unscaled(4, false)); - arr_2.append(FixedTrait::new_unscaled(5, false)); - arr_2.append(FixedTrait::new_unscaled(16, false)); - arr_2.append(FixedTrait::new_unscaled(17, false)); - arr_2.append(FixedTrait::new_unscaled(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(200000000000)] + fn tensor_greater() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(200000000000)] -fn tensor_greater_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - arr_1.append(FixedTrait::new_unscaled(8, false)); - arr_1.append(FixedTrait::new_unscaled(9, false)); - arr_1.append(FixedTrait::new_unscaled(10, false)); - arr_1.append(FixedTrait::new_unscaled(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(0, false)); - arr_2.append(FixedTrait::new_unscaled(1, false)); - arr_2.append(FixedTrait::new_unscaled(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} // ===== 3D ===== // -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(2, true)); - arr_2.append(FixedTrait::new_unscaled(3, true)); - arr_2.append(FixedTrait::new_unscaled(4, false)); - arr_2.append(FixedTrait::new_unscaled(5, false)); - arr_2.append(FixedTrait::new_unscaled(16, false)); - arr_2.append(FixedTrait::new_unscaled(17, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(0, false)); - arr_2.append(FixedTrait::new_unscaled(1, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo b/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo index ae9a42af2..413f7c24b 100644 --- a/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo @@ -1,286 +1,313 @@ -use array::SpanTrait; -use array::{ArrayTrait}; +// ===== 1D ===== // -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; -use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::ArrayTrait; -// ===== 1D ===== // + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); + #[test] + #[available_gas(2000000000000)] + fn tensor_greater() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(2, true)); + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); - let extra = Option::::None(()); + let extra = Option::::None(()); - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } + // ===== 2D ===== // -#[test] -#[available_gas(200000000000)] -fn tensor_greater_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - arr_1.append(FixedTrait::new_unscaled(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(2, true)); - arr_2.append(FixedTrait::new_unscaled(3, true)); - arr_2.append(FixedTrait::new_unscaled(4, false)); - arr_2.append(FixedTrait::new_unscaled(5, false)); - arr_2.append(FixedTrait::new_unscaled(16, false)); - arr_2.append(FixedTrait::new_unscaled(17, false)); - arr_2.append(FixedTrait::new_unscaled(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(200000000000)] + fn tensor_greater() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(200000000000)] -fn tensor_greater_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - arr_1.append(FixedTrait::new_unscaled(8, false)); - arr_1.append(FixedTrait::new_unscaled(9, false)); - arr_1.append(FixedTrait::new_unscaled(10, false)); - arr_1.append(FixedTrait::new_unscaled(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(0, false)); - arr_2.append(FixedTrait::new_unscaled(1, false)); - arr_2.append(FixedTrait::new_unscaled(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} // ===== 3D ===== // -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(10, false)); - arr_2.append(FixedTrait::new_unscaled(11, false)); - arr_2.append(FixedTrait::new_unscaled(2, true)); - arr_2.append(FixedTrait::new_unscaled(3, true)); - arr_2.append(FixedTrait::new_unscaled(4, false)); - arr_2.append(FixedTrait::new_unscaled(5, false)); - arr_2.append(FixedTrait::new_unscaled(16, false)); - arr_2.append(FixedTrait::new_unscaled(17, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new_unscaled(0, false)); - arr_1.append(FixedTrait::new_unscaled(1, false)); - arr_1.append(FixedTrait::new_unscaled(2, false)); - arr_1.append(FixedTrait::new_unscaled(3, false)); - arr_1.append(FixedTrait::new_unscaled(4, false)); - arr_1.append(FixedTrait::new_unscaled(5, false)); - arr_1.append(FixedTrait::new_unscaled(6, false)); - arr_1.append(FixedTrait::new_unscaled(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new_unscaled(0, false)); - arr_2.append(FixedTrait::new_unscaled(1, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } diff --git a/src/tests/operators/math/greater/greater_i32_test.cairo b/src/tests/operators/math/greater/greater_i32_test.cairo index 6a4f904ef..6ce3a0814 100644 --- a/src/tests/operators/math/greater/greater_i32_test.cairo +++ b/src/tests/operators/math/greater/greater_i32_test.cairo @@ -1,285 +1,311 @@ -use array::SpanTrait; -use array::{ArrayTrait}; +// ===== 1D ===== // -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; -// ===== 1D ===== // + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_1D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(2, true)); + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); - let extra = Option::::None(()); + let extra = Option::::None(()); - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } + // ===== 2D ===== // -#[test] -#[available_gas(200000000000)] -fn tensor_greater_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(2, true)); - arr_2.append(IntegerTrait::new(3, true)); - arr_2.append(IntegerTrait::new(4, false)); - arr_2.append(IntegerTrait::new(5, false)); - arr_2.append(IntegerTrait::new(16, false)); - arr_2.append(IntegerTrait::new(17, false)); - arr_2.append(IntegerTrait::new(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_2D() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + arr_2.append(IntegerTrait::new(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_broadcast_2D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + arr_1.append(IntegerTrait::new(9, false)); + arr_1.append(IntegerTrait::new(10, false)); + arr_1.append(IntegerTrait::new(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + arr_2.append(IntegerTrait::new(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(200000000000)] -fn tensor_greater_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - arr_1.append(IntegerTrait::new(9, false)); - arr_1.append(IntegerTrait::new(10, false)); - arr_1.append(IntegerTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(0, false)); - arr_2.append(IntegerTrait::new(1, false)); - arr_2.append(IntegerTrait::new(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} // ===== 3D ===== // -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(2, true)); - arr_2.append(IntegerTrait::new(3, true)); - arr_2.append(IntegerTrait::new(4, false)); - arr_2.append(IntegerTrait::new(5, false)); - arr_2.append(IntegerTrait::new(16, false)); - arr_2.append(IntegerTrait::new(17, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000000000)] -fn tensor_greater_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(0, false)); - arr_2.append(IntegerTrait::new(1, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_3D() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_broadcast_3D() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } diff --git a/src/tests/operators/math/greater/greater_u32_test.cairo b/src/tests/operators/math/greater/greater_u32_test.cairo index 4456fcebf..add8a5bf4 100644 --- a/src/tests/operators/math/greater/greater_u32_test.cairo +++ b/src/tests/operators/math/greater/greater_u32_test.cairo @@ -1,289 +1,310 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - // ===== 1D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_greater_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_greater() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10); - arr_2.append(11); - arr_2.append(1); + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(1); - let extra = Option::::None(()); + let extra = Option::::None(()); - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -// ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_greater_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(7); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10); - arr_2.append(11); - arr_2.append(12); - arr_2.append(13); - arr_2.append(4); - arr_2.append(5); - arr_2.append(16); - arr_2.append(17); - arr_2.append(18); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} +// ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_greater_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(5); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - arr_1.append(9); - arr_1.append(10); - arr_1.append(11); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0); - arr_2.append(1); - arr_2.append(2); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_greater() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_greater_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_greater_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(7_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10_u32); - arr_2.append(11_u32); - arr_2.append(12_u32); - arr_2.append(13_u32); - arr_2.append(4_u32); - arr_2.append(5_u32); - arr_2.append(16_u32); - arr_2.append(17_u32); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_greater() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0_u32); + arr_1.append(1_u32); + arr_1.append(2_u32); + arr_1.append(3_u32); + arr_1.append(4_u32); + arr_1.append(7_u32); + arr_1.append(6_u32); + arr_1.append(7_u32); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10_u32); + arr_2.append(11_u32); + arr_2.append(12_u32); + arr_2.append(13_u32); + arr_2.append(4_u32); + arr_2.append(5_u32); + arr_2.append(16_u32); + arr_2.append(17_u32); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_greater_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_greater_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(5); - arr_1.append(6); - arr_1.append(7); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0); - arr_2.append(1); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} From 15a133e22394a6096dc993c0555e355d230a1ccb Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 10:23:56 +0300 Subject: [PATCH 024/126] refactor tensor greater_equal tests --- .../math/greater/greater_i32_test.cairo | 12 +- .../greater_equal/greater_equal_fp_test.cairo | 137 +---- .../greater_equal_fp16x16_test.cairo | 317 ++++++++++ .../greater_equal_fp8x23_test.cairo | 317 ++++++++++ .../greater_equal_i32_test.cairo | 439 ++++++++++---- .../greater_equal_u32_test.cairo | 559 +++++++++--------- 6 files changed, 1240 insertions(+), 541 deletions(-) create mode 100644 src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo create mode 100644 src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo diff --git a/src/tests/operators/math/greater/greater_i32_test.cairo b/src/tests/operators/math/greater/greater_i32_test.cairo index 6ce3a0814..2dc3fd5aa 100644 --- a/src/tests/operators/math/greater/greater_i32_test.cairo +++ b/src/tests/operators/math/greater/greater_i32_test.cairo @@ -11,7 +11,7 @@ mod tensor_1D { #[test] #[available_gas(2000000000000)] - fn tensor_greater_1D() { + fn tensor_greater() { let mut sizes = ArrayTrait::new(); sizes.append(3); @@ -54,7 +54,7 @@ mod tensor_2D { #[test] #[available_gas(200000000000)] - fn tensor_greater_2D() { + fn tensor_greater() { let mut sizes = ArrayTrait::new(); sizes.append(3); sizes.append(3); @@ -115,7 +115,7 @@ mod tensor_2D { #[test] #[available_gas(200000000000)] - fn tensor_greater_broadcast_2D() { + fn tensor_greater_broadcast() { let mut sizes_1 = ArrayTrait::new(); sizes_1.append(4); sizes_1.append(3); @@ -196,7 +196,7 @@ mod tensor_3D { #[test] #[available_gas(2000000000000)] - fn tensor_greater_3D() { + fn tensor_greater() { let mut sizes = ArrayTrait::new(); sizes.append(2); sizes.append(2); @@ -254,7 +254,7 @@ mod tensor_3D { #[test] #[available_gas(2000000000000)] - fn tensor_greater_broadcast_3D() { + fn tensor_greater_broadcast() { let mut sizes_1 = ArrayTrait::new(); sizes_1.append(2); sizes_1.append(2); @@ -299,7 +299,7 @@ mod tensor_3D { let result_b = tensor_a.greater(@tensor_b); assert(*result_b.data.at(0) == 0, 'result[0] = 0'); assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); assert(*result_b.data.at(3) == 1, 'result[3] = 1'); assert(*result_b.data.at(4) == 1, 'result[4] = 1'); assert(*result_b.data.at(5) == 1, 'result[5] = 1'); diff --git a/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo index ac1784173..bb73d4adc 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo @@ -1,135 +1,2 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp;use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; - - -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_fp() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(10, false)); - arr_2.append(FixedTrait::new(11, false)); - arr_2.append(FixedTrait::new(2, true)); - arr_2.append(FixedTrait::new(3, true)); - arr_2.append(FixedTrait::new(4, false)); - arr_2.append(FixedTrait::new(5, false)); - arr_2.append(FixedTrait::new(16, false)); - arr_2.append(FixedTrait::new(17, false)); - arr_2.append(FixedTrait::new(18, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_fp_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - arr_1.append(FixedTrait::new(9, false)); - arr_1.append(FixedTrait::new(10, false)); - arr_1.append(FixedTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(0, false)); - arr_2.append(FixedTrait::new(1, false)); - arr_2.append(FixedTrait::new(2, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} +mod greater_equal_fp8x23_test; +mod greater_equal_fp16x16_test; diff --git a/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo new file mode 100644 index 000000000..ccb842082 --- /dev/null +++ b/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo @@ -0,0 +1,317 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_16x16::FP16x16Impl + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_16x16::FP16x16Impl + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_16x16::FP16x16Impl + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} diff --git a/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo new file mode 100644 index 000000000..ee0588820 --- /dev/null +++ b/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo @@ -0,0 +1,317 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_8x23::FP8x23Impl + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_8x23::FP8x23Impl + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_8x23::FP8x23Impl + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} diff --git a/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo index 6d1c7b4cd..4039e559e 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo @@ -1,134 +1,311 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_i32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(2, true)); - arr_2.append(IntegerTrait::new(3, true)); - arr_2.append(IntegerTrait::new(4, false)); - arr_2.append(IntegerTrait::new(5, false)); - arr_2.append(IntegerTrait::new(16, false)); - arr_2.append(IntegerTrait::new(17, false)); - arr_2.append(IntegerTrait::new(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + arr_2.append(IntegerTrait::new(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_greater_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + arr_1.append(IntegerTrait::new(9, false)); + arr_1.append(IntegerTrait::new(10, false)); + arr_1.append(IntegerTrait::new(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + arr_2.append(IntegerTrait::new(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_i32_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - arr_1.append(IntegerTrait::new(9, false)); - arr_1.append(IntegerTrait::new(10, false)); - arr_1.append(IntegerTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(0, false)); - arr_2.append(IntegerTrait::new(1, false)); - arr_2.append(IntegerTrait::new(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_greater_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } diff --git a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo index 308071091..80ef9ec8d 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo @@ -1,289 +1,310 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - // ===== 1D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_1D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10); - arr_2.append(11); - arr_2.append(2); + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(1); - let extra = Option::::None(()); + let extra = Option::::None(()); - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 0'); + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -// ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_2D() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(7); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10); - arr_2.append(11); - arr_2.append(12); - arr_2.append(13); - arr_2.append(4); - arr_2.append(5); - arr_2.append(16); - arr_2.append(17); - arr_2.append(18); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 1, 'result[4] = 0'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} +// ===== 2D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_broadcast_2D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(5); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - arr_1.append(9); - arr_1.append(10); - arr_1.append(11); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0); - arr_2.append(1); - arr_2.append(2); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_greater_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data.at(9) == 0, 'result[9] = 0'); + assert(*result_a.data.at(10) == 0, 'result[10] = 0'); + assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data.at(9) == 1, 'result[9] = 1'); + assert(*result_b.data.at(10) == 1, 'result[10] = 1'); + assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } // ===== 3D ===== // -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_3D() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0_u32); - arr_1.append(1_u32); - arr_1.append(2_u32); - arr_1.append(3_u32); - arr_1.append(4_u32); - arr_1.append(7_u32); - arr_1.append(6_u32); - arr_1.append(7_u32); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10_u32); - arr_2.append(11_u32); - arr_2.append(12_u32); - arr_2.append(13_u32); - arr_2.append(4_u32); - arr_2.append(5_u32); - arr_2.append(16_u32); - arr_2.append(17_u32); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_greater_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0_u32); + arr_1.append(1_u32); + arr_1.append(2_u32); + arr_1.append(3_u32); + arr_1.append(4_u32); + arr_1.append(7_u32); + arr_1.append(6_u32); + arr_1.append(7_u32); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10_u32); + arr_2.append(11_u32); + arr_2.append(12_u32); + arr_2.append(13_u32); + arr_2.append(4_u32); + arr_2.append(5_u32); + arr_2.append(16_u32); + arr_2.append(17_u32); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.greater_equal(@tensor_b); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.greater_equal(@tensor_a); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_greater_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.greater_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 0, 'result[3] = 0'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 0, 'result[6] = 0'); + assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.greater_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_greater_equal_broadcast_3D() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(2); - sizes_1.append(2); - sizes_1.append(2); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(2); - sizes_2.append(1); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(5); - arr_1.append(6); - arr_1.append(7); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0); - arr_2.append(1); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} From 69cb05006f26166b43b66ca548fe11a975ac038d Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 10:49:45 +0300 Subject: [PATCH 025/126] refactor tensor less tests --- .../operators/math/less/less_fp_test.cairo | 136 +----- .../less/less_fp_test/less_fp16x16_test.cairo | 313 +++++++++++++ .../less/less_fp_test/less_fp8x23_test.cairo | 313 +++++++++++++ .../operators/math/less/less_i32_test.cairo | 441 ++++++++++++------ .../operators/math/less/less_u32_test.cairo | 437 +++++++++++------ 5 files changed, 1243 insertions(+), 397 deletions(-) create mode 100644 src/tests/operators/math/less/less_fp_test/less_fp16x16_test.cairo create mode 100644 src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo diff --git a/src/tests/operators/math/less/less_fp_test.cairo b/src/tests/operators/math/less/less_fp_test.cairo index a92f04346..65177e165 100644 --- a/src/tests/operators/math/less/less_fp_test.cairo +++ b/src/tests/operators/math/less/less_fp_test.cairo @@ -1,134 +1,2 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp;use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; - -#[test] -#[available_gas(2000000)] -fn tensor_less_fp() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(10, false)); - arr_2.append(FixedTrait::new(11, false)); - arr_2.append(FixedTrait::new(2, true)); - arr_2.append(FixedTrait::new(3, true)); - arr_2.append(FixedTrait::new(4, false)); - arr_2.append(FixedTrait::new(5, false)); - arr_2.append(FixedTrait::new(16, false)); - arr_2.append(FixedTrait::new(17, false)); - arr_2.append(FixedTrait::new(18, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_less_fp_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - arr_1.append(FixedTrait::new(9, false)); - arr_1.append(FixedTrait::new(10, false)); - arr_1.append(FixedTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(0, false)); - arr_2.append(FixedTrait::new(1, false)); - arr_2.append(FixedTrait::new(2, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} +mod less_fp8x23_test; +mod less_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/math/less/less_fp_test/less_fp16x16_test.cairo b/src/tests/operators/math/less/less_fp_test/less_fp16x16_test.cairo new file mode 100644 index 000000000..7d3237018 --- /dev/null +++ b/src/tests/operators/math/less/less_fp_test/less_fp16x16_test.cairo @@ -0,0 +1,313 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + + #[test] + #[available_gas(200000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_less_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data.at(9) == 1, 'result[9] = 1'); + assert(*result_a.data.at(10) == 1, 'result[10] = 1'); + assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data.at(9) == 0, 'result[9] = 1'); + assert(*result_b.data.at(10) == 0, 'result[10] = 1'); + assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + + #[test] + #[available_gas(2000000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} diff --git a/src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo b/src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo new file mode 100644 index 000000000..acbaff4b9 --- /dev/null +++ b/src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo @@ -0,0 +1,313 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + + #[test] + #[available_gas(200000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_less_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data.at(9) == 1, 'result[9] = 1'); + assert(*result_a.data.at(10) == 1, 'result[10] = 1'); + assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data.at(9) == 0, 'result[9] = 1'); + assert(*result_b.data.at(10) == 0, 'result[10] = 1'); + assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + + #[test] + #[available_gas(2000000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} diff --git a/src/tests/operators/math/less/less_i32_test.cairo b/src/tests/operators/math/less/less_i32_test.cairo index 7f04b2b8e..0abd2751d 100644 --- a/src/tests/operators/math/less/less_i32_test.cairo +++ b/src/tests/operators/math/less/less_i32_test.cairo @@ -1,136 +1,311 @@ -use array::SpanTrait; -use array::{ArrayTrait}; - -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - - -#[test] -#[available_gas(2000000)] -fn tensor_less_i32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(2, true)); - arr_2.append(IntegerTrait::new(3, true)); - arr_2.append(IntegerTrait::new(4, false)); - arr_2.append(IntegerTrait::new(5, false)); - arr_2.append(IntegerTrait::new(16, false)); - arr_2.append(IntegerTrait::new(17, false)); - arr_2.append(IntegerTrait::new(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + + #[test] + #[available_gas(200000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + arr_2.append(IntegerTrait::new(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_less_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + arr_1.append(IntegerTrait::new(9, false)); + arr_1.append(IntegerTrait::new(10, false)); + arr_1.append(IntegerTrait::new(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + arr_2.append(IntegerTrait::new(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data.at(9) == 1, 'result[9] = 1'); + assert(*result_a.data.at(10) == 1, 'result[10] = 1'); + assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data.at(9) == 0, 'result[9] = 1'); + assert(*result_b.data.at(10) == 0, 'result[10] = 1'); + assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_less_i32_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - arr_1.append(IntegerTrait::new(9, false)); - arr_1.append(IntegerTrait::new(10, false)); - arr_1.append(IntegerTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(0, false)); - arr_2.append(IntegerTrait::new(1, false)); - arr_2.append(IntegerTrait::new(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } diff --git a/src/tests/operators/math/less/less_u32_test.cairo b/src/tests/operators/math/less/less_u32_test.cairo index 9bfbd3e4d..cf6b3c8b8 100644 --- a/src/tests/operators/math/less/less_u32_test.cairo +++ b/src/tests/operators/math/less/less_u32_test.cairo @@ -1,133 +1,310 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - -#[test] -#[available_gas(2000000)] -fn tensor_less_u32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(7); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10); - arr_2.append(11); - arr_2.append(12); - arr_2.append(13); - arr_2.append(4); - arr_2.append(5); - arr_2.append(16); - arr_2.append(17); - arr_2.append(18); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(1); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_less_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data.at(9) == 1, 'result[9] = 1'); + assert(*result_a.data.at(10) == 1, 'result[10] = 1'); + assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data.at(9) == 0, 'result[9] = 0'); + assert(*result_b.data.at(10) == 0, 'result[10] = 0'); + assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_less_u32_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(5); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - arr_1.append(9); - arr_1.append(10); - arr_1.append(11); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0); - arr_2.append(1); - arr_2.append(2); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_less() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0_u32); + arr_1.append(1_u32); + arr_1.append(2_u32); + arr_1.append(3_u32); + arr_1.append(4_u32); + arr_1.append(7_u32); + arr_1.append(6_u32); + arr_1.append(7_u32); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10_u32); + arr_2.append(11_u32); + arr_2.append(12_u32); + arr_2.append(13_u32); + arr_2.append(4_u32); + arr_2.append(5_u32); + arr_2.append(16_u32); + arr_2.append(17_u32); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 0, 'result[4] = 0'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_less_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less(@tensor_a); + assert(*result_a.data.at(0) == 0, 'result[0] = 0'); + assert(*result_a.data.at(1) == 0, 'result[1] = 0'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less(@tensor_b); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } + From f55af597acbba8968fe49cad68f2f4098ebe49b0 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 11:02:07 +0300 Subject: [PATCH 026/126] refactor tensor less_equal tests --- .../operators/math/less/less_i32_test.cairo | 12 +- .../math/less_equal/less_equal_fp_test.cairo | 136 +----- .../less_equal_fp16x16_test.cairo | 314 +++++++++++++ .../less_equal_fp8x23_test.cairo | 314 +++++++++++++ .../math/less_equal/less_equal_i32_test.cairo | 440 ++++++++++++------ .../math/less_equal/less_equal_u32_test.cairo | 437 +++++++++++------ 6 files changed, 1251 insertions(+), 402 deletions(-) create mode 100644 src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo create mode 100644 src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo diff --git a/src/tests/operators/math/less/less_i32_test.cairo b/src/tests/operators/math/less/less_i32_test.cairo index 0abd2751d..9cc413f72 100644 --- a/src/tests/operators/math/less/less_i32_test.cairo +++ b/src/tests/operators/math/less/less_i32_test.cairo @@ -299,12 +299,12 @@ mod tensor_3D { let result_b = tensor_a.less(@tensor_b); assert(*result_b.data.at(0) == 0, 'result[0] = 0'); assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/math/less_equal/less_equal_fp_test.cairo b/src/tests/operators/math/less_equal/less_equal_fp_test.cairo index c821ca3e5..cc5230ac6 100644 --- a/src/tests/operators/math/less_equal/less_equal_fp_test.cairo +++ b/src/tests/operators/math/less_equal/less_equal_fp_test.cairo @@ -1,134 +1,2 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp;use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; - -#[test] -#[available_gas(2000000)] -fn tensor_less_equal_fp() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(10, false)); - arr_2.append(FixedTrait::new(11, false)); - arr_2.append(FixedTrait::new(2, true)); - arr_2.append(FixedTrait::new(3, true)); - arr_2.append(FixedTrait::new(4, false)); - arr_2.append(FixedTrait::new(5, false)); - arr_2.append(FixedTrait::new(16, false)); - arr_2.append(FixedTrait::new(17, false)); - arr_2.append(FixedTrait::new(18, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} - -#[test] -#[available_gas(2000000)] -fn tensor_less_equal_fp_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(FixedTrait::new(0, false)); - arr_1.append(FixedTrait::new(1, false)); - arr_1.append(FixedTrait::new(2, false)); - arr_1.append(FixedTrait::new(3, false)); - arr_1.append(FixedTrait::new(4, false)); - arr_1.append(FixedTrait::new(5, false)); - arr_1.append(FixedTrait::new(6, false)); - arr_1.append(FixedTrait::new(7, false)); - arr_1.append(FixedTrait::new(8, false)); - arr_1.append(FixedTrait::new(9, false)); - arr_1.append(FixedTrait::new(10, false)); - arr_1.append(FixedTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(FixedTrait::new(0, false)); - arr_2.append(FixedTrait::new(1, false)); - arr_2.append(FixedTrait::new(2, false)); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); - - let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); -} +mod less_equal_fp8x23_test; +mod less_equal_fp16x16_test; diff --git a/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo b/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo new file mode 100644 index 000000000..2ed2b5023 --- /dev/null +++ b/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo @@ -0,0 +1,314 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + + #[test] + #[available_gas(200000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_less_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data.at(9) == 1, 'result[9] = 1'); + assert(*result_a.data.at(10) == 1, 'result[10] = 1'); + assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data.at(9) == 0, 'result[9] = 1'); + assert(*result_b.data.at(10) == 0, 'result[10] = 1'); + assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} diff --git a/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo b/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo new file mode 100644 index 000000000..c9456396a --- /dev/null +++ b/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo @@ -0,0 +1,314 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + + #[test] + #[available_gas(200000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + arr_2.append(FixedTrait::new_unscaled(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_less_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + arr_1.append(FixedTrait::new_unscaled(8, false)); + arr_1.append(FixedTrait::new_unscaled(9, false)); + arr_1.append(FixedTrait::new_unscaled(10, false)); + arr_1.append(FixedTrait::new_unscaled(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + arr_2.append(FixedTrait::new_unscaled(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data.at(9) == 1, 'result[9] = 1'); + assert(*result_a.data.at(10) == 1, 'result[10] = 1'); + assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data.at(9) == 0, 'result[9] = 1'); + assert(*result_b.data.at(10) == 0, 'result[10] = 1'); + assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(10, false)); + arr_2.append(FixedTrait::new_unscaled(11, false)); + arr_2.append(FixedTrait::new_unscaled(2, true)); + arr_2.append(FixedTrait::new_unscaled(3, true)); + arr_2.append(FixedTrait::new_unscaled(4, false)); + arr_2.append(FixedTrait::new_unscaled(5, false)); + arr_2.append(FixedTrait::new_unscaled(16, false)); + arr_2.append(FixedTrait::new_unscaled(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(FixedTrait::new_unscaled(0, false)); + arr_1.append(FixedTrait::new_unscaled(1, false)); + arr_1.append(FixedTrait::new_unscaled(2, false)); + arr_1.append(FixedTrait::new_unscaled(3, false)); + arr_1.append(FixedTrait::new_unscaled(4, false)); + arr_1.append(FixedTrait::new_unscaled(5, false)); + arr_1.append(FixedTrait::new_unscaled(6, false)); + arr_1.append(FixedTrait::new_unscaled(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(FixedTrait::new_unscaled(0, false)); + arr_2.append(FixedTrait::new_unscaled(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} diff --git a/src/tests/operators/math/less_equal/less_equal_i32_test.cairo b/src/tests/operators/math/less_equal/less_equal_i32_test.cairo index e85236e3c..cb06e188b 100644 --- a/src/tests/operators/math/less_equal/less_equal_i32_test.cairo +++ b/src/tests/operators/math/less_equal/less_equal_i32_test.cairo @@ -1,135 +1,311 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - - -#[test] -#[available_gas(2000000)] -fn tensor_less_equal_i32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(10, false)); - arr_2.append(IntegerTrait::new(11, false)); - arr_2.append(IntegerTrait::new(2, true)); - arr_2.append(IntegerTrait::new(3, true)); - arr_2.append(IntegerTrait::new(4, false)); - arr_2.append(IntegerTrait::new(5, false)); - arr_2.append(IntegerTrait::new(16, false)); - arr_2.append(IntegerTrait::new(17, false)); - arr_2.append(IntegerTrait::new(18, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + + #[test] + #[available_gas(200000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + arr_2.append(IntegerTrait::new(18, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(200000000000)] + fn tensor_less_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + arr_1.append(IntegerTrait::new(8, false)); + arr_1.append(IntegerTrait::new(9, false)); + arr_1.append(IntegerTrait::new(10, false)); + arr_1.append(IntegerTrait::new(11, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + arr_2.append(IntegerTrait::new(2, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data.at(9) == 1, 'result[9] = 1'); + assert(*result_a.data.at(10) == 1, 'result[10] = 1'); + assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 1'); + assert(*result_b.data.at(4) == 0, 'result[4] = 1'); + assert(*result_b.data.at(5) == 0, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data.at(9) == 0, 'result[9] = 1'); + assert(*result_b.data.at(10) == 0, 'result[10] = 1'); + assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_less_equal_i32_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(IntegerTrait::new(0, false)); - arr_1.append(IntegerTrait::new(1, false)); - arr_1.append(IntegerTrait::new(2, false)); - arr_1.append(IntegerTrait::new(3, false)); - arr_1.append(IntegerTrait::new(4, false)); - arr_1.append(IntegerTrait::new(5, false)); - arr_1.append(IntegerTrait::new(6, false)); - arr_1.append(IntegerTrait::new(7, false)); - arr_1.append(IntegerTrait::new(8, false)); - arr_1.append(IntegerTrait::new(9, false)); - arr_1.append(IntegerTrait::new(10, false)); - arr_1.append(IntegerTrait::new(11, false)); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(IntegerTrait::new(0, false)); - arr_2.append(IntegerTrait::new(1, false)); - arr_2.append(IntegerTrait::new(2, false)); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(10, false)); + arr_2.append(IntegerTrait::new(11, false)); + arr_2.append(IntegerTrait::new(2, true)); + arr_2.append(IntegerTrait::new(3, true)); + arr_2.append(IntegerTrait::new(4, false)); + arr_2.append(IntegerTrait::new(5, false)); + arr_2.append(IntegerTrait::new(16, false)); + arr_2.append(IntegerTrait::new(17, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data.at(3) == 0, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 1'); + assert(*result_b.data.at(1) == 0, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 1, 'result[3] = 1'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 1'); + assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000000000)] + fn tensor_less_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(IntegerTrait::new(0, false)); + arr_1.append(IntegerTrait::new(1, false)); + arr_1.append(IntegerTrait::new(2, false)); + arr_1.append(IntegerTrait::new(3, false)); + arr_1.append(IntegerTrait::new(4, false)); + arr_1.append(IntegerTrait::new(5, false)); + arr_1.append(IntegerTrait::new(6, false)); + arr_1.append(IntegerTrait::new(7, false)); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(IntegerTrait::new(0, false)); + arr_2.append(IntegerTrait::new(1, false)); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } diff --git a/src/tests/operators/math/less_equal/less_equal_u32_test.cairo b/src/tests/operators/math/less_equal/less_equal_u32_test.cairo index da59fb24d..97434920e 100644 --- a/src/tests/operators/math/less_equal/less_equal_u32_test.cairo +++ b/src/tests/operators/math/less_equal/less_equal_u32_test.cairo @@ -1,133 +1,310 @@ -use array::SpanTrait; -use array::{ArrayTrait}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - -#[test] -#[available_gas(2000000)] -fn tensor_less_equal_u32() { - let mut sizes = ArrayTrait::new(); - sizes.append(3); - sizes.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(7); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(10); - arr_2.append(11); - arr_2.append(12); - arr_2.append(13); - arr_2.append(4); - arr_2.append(5); - arr_2.append(16); - arr_2.append(17); - arr_2.append(18); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); - - let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(1); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(3); + sizes.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(7); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10); + arr_2.append(11); + arr_2.append(12); + arr_2.append(13); + arr_2.append(4); + arr_2.append(5); + arr_2.append(16); + arr_2.append(17); + arr_2.append(18); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_less_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(4); + sizes_1.append(3); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(3); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + arr_1.append(8); + arr_1.append(9); + arr_1.append(10); + arr_1.append(11); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + arr_2.append(2); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data.at(9) == 1, 'result[9] = 1'); + assert(*result_a.data.at(10) == 1, 'result[10] = 1'); + assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data.at(9) == 0, 'result[9] = 0'); + assert(*result_b.data.at(10) == 0, 'result[10] = 0'); + assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } -#[test] -#[available_gas(2000000)] -fn tensor_less_equal_u32_broadcast() { - let mut sizes_1 = ArrayTrait::new(); - sizes_1.append(4); - sizes_1.append(3); - - let mut sizes_2 = ArrayTrait::new(); - sizes_2.append(1); - sizes_2.append(3); - - let mut arr_1 = ArrayTrait::::new(); - arr_1.append(0); - arr_1.append(1); - arr_1.append(2); - arr_1.append(3); - arr_1.append(4); - arr_1.append(5); - arr_1.append(6); - arr_1.append(7); - arr_1.append(8); - arr_1.append(9); - arr_1.append(10); - arr_1.append(11); - - let mut arr_2 = ArrayTrait::::new(); - arr_2.append(0); - arr_2.append(1); - arr_2.append(2); - - let extra = Option::::None(()); - - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); - - let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); - - assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); - - let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); - - assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use array::{ArrayTrait}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(2000000)] + fn tensor_less_equal() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0_u32); + arr_1.append(1_u32); + arr_1.append(2_u32); + arr_1.append(3_u32); + arr_1.append(4_u32); + arr_1.append(7_u32); + arr_1.append(6_u32); + arr_1.append(7_u32); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(10_u32); + arr_2.append(11_u32); + arr_2.append(12_u32); + arr_2.append(13_u32); + arr_2.append(4_u32); + arr_2.append(5_u32); + arr_2.append(16_u32); + arr_2.append(17_u32); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + + let result_a = tensor_a.less_equal(@tensor_b); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 0, 'result[5] = 0'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_b.less_equal(@tensor_a); + assert(*result_b.data.at(0) == 0, 'result[0] = 0'); + assert(*result_b.data.at(1) == 0, 'result[1] = 0'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 1, 'result[4] = 1'); + assert(*result_b.data.at(5) == 1, 'result[5] = 1'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } + + #[test] + #[available_gas(2000000)] + fn tensor_less_equal_broadcast() { + let mut sizes_1 = ArrayTrait::new(); + sizes_1.append(2); + sizes_1.append(2); + sizes_1.append(2); + + let mut sizes_2 = ArrayTrait::new(); + sizes_2.append(1); + sizes_2.append(2); + sizes_2.append(1); + + let mut arr_1 = ArrayTrait::::new(); + arr_1.append(0); + arr_1.append(1); + arr_1.append(2); + arr_1.append(3); + arr_1.append(4); + arr_1.append(5); + arr_1.append(6); + arr_1.append(7); + + let mut arr_2 = ArrayTrait::::new(); + arr_2.append(0); + arr_2.append(1); + + let extra = Option::::None(()); + + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + + let result_a = tensor_b.less_equal(@tensor_a); + assert(*result_a.data.at(0) == 1, 'result[0] = 1'); + assert(*result_a.data.at(1) == 1, 'result[1] = 1'); + assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data.at(3) == 1, 'result[3] = 1'); + assert(*result_a.data.at(4) == 1, 'result[4] = 1'); + assert(*result_a.data.at(5) == 1, 'result[5] = 1'); + assert(*result_a.data.at(6) == 1, 'result[6] = 1'); + assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + + assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + + let result_b = tensor_a.less_equal(@tensor_b); + assert(*result_b.data.at(0) == 1, 'result[0] = 1'); + assert(*result_b.data.at(1) == 1, 'result[1] = 1'); + assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data.at(3) == 0, 'result[3] = 0'); + assert(*result_b.data.at(4) == 0, 'result[4] = 0'); + assert(*result_b.data.at(5) == 0, 'result[5] = 0'); + assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + + assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); + } } + From 7a66bd8d3f8b0a8182ca06921ff9f9818d00290f Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 11:35:22 +0300 Subject: [PATCH 027/126] refactor tensor exp tests --- src/tests/operators/math.cairo | 2 +- src/tests/operators/math/exp.cairo | 3 + .../operators/math/exp/exp_fp_test.cairo | 2 + .../exp/exp_fp_test/exp_fp16x16_test.cairo | 79 +++++++++++++++++++ .../exp/exp_fp_test/exp_fp8x23_test.cairo | 78 ++++++++++++++++++ .../operators/math/exp/exp_i32_test.cairo | 79 +++++++++++++++++++ .../operators/math/exp/exp_u32_test.cairo | 79 +++++++++++++++++++ src/tests/operators/math/exp_test.cairo | 19 ----- 8 files changed, 321 insertions(+), 20 deletions(-) create mode 100644 src/tests/operators/math/exp.cairo create mode 100644 src/tests/operators/math/exp/exp_fp_test.cairo create mode 100644 src/tests/operators/math/exp/exp_fp_test/exp_fp16x16_test.cairo create mode 100644 src/tests/operators/math/exp/exp_fp_test/exp_fp8x23_test.cairo create mode 100644 src/tests/operators/math/exp/exp_i32_test.cairo create mode 100644 src/tests/operators/math/exp/exp_u32_test.cairo delete mode 100644 src/tests/operators/math/exp_test.cairo diff --git a/src/tests/operators/math.cairo b/src/tests/operators/math.cairo index 4fe9a7d63..cb5d99ec6 100644 --- a/src/tests/operators/math.cairo +++ b/src/tests/operators/math.cairo @@ -3,7 +3,7 @@ mod argmin; mod max_test; mod min_test; mod reduce_sum_test; -mod exp_test; +mod exp; mod equal; mod greater; mod greater_equal; diff --git a/src/tests/operators/math/exp.cairo b/src/tests/operators/math/exp.cairo new file mode 100644 index 000000000..d6c664da2 --- /dev/null +++ b/src/tests/operators/math/exp.cairo @@ -0,0 +1,3 @@ +mod exp_u32_test; +mod exp_i32_test; +mod exp_fp_test; diff --git a/src/tests/operators/math/exp/exp_fp_test.cairo b/src/tests/operators/math/exp/exp_fp_test.cairo new file mode 100644 index 000000000..4cbd312e1 --- /dev/null +++ b/src/tests/operators/math/exp/exp_fp_test.cairo @@ -0,0 +1,2 @@ +mod exp_fp8x23_test; +mod exp_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/math/exp/exp_fp_test/exp_fp16x16_test.cairo b/src/tests/operators/math/exp/exp_fp_test/exp_fp16x16_test.cairo new file mode 100644 index 000000000..9b7161134 --- /dev/null +++ b/src/tests/operators/math/exp/exp_fp_test/exp_fp16x16_test.cairo @@ -0,0 +1,79 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 1316288, 'result[3] = 20.085...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 1316288, 'result[3] = 20.085...'); + assert((*result.at(4).mag).into() == 3577984, 'result[3] = 54.5981...'); + assert((*result.at(5).mag).into() == 9726080, 'result[3] = 148.4131...'); + assert((*result.at(6).mag).into() == 26437888, 'result[3] = 403.4287...'); + assert((*result.at(7).mag).into() == 71866368, 'result[3] = 1096.6331...'); + } +} + diff --git a/src/tests/operators/math/exp/exp_fp_test/exp_fp8x23_test.cairo b/src/tests/operators/math/exp/exp_fp_test/exp_fp8x23_test.cairo new file mode 100644 index 000000000..84df3f05c --- /dev/null +++ b/src/tests/operators/math/exp/exp_fp_test/exp_fp8x23_test.cairo @@ -0,0 +1,78 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 8388608, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 22802598, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 61983880, 'result[2] = 7.389...'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 8388608, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 22802598, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 61983880, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 168489680, 'result[3] = 20.085...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 8388608, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 22802598, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 61983880, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 168489680, 'result[3] = 20.085...'); + assert((*result.at(4).mag).into() == 458002400, 'result[3] = 54.5981...'); + assert((*result.at(5).mag).into() == 1244979584, 'result[3] = 148.4131...'); + assert((*result.at(6).mag).into() == 3384205312, 'result[3] = 403.4287...'); + assert((*result.at(7).mag).into() == 9199223808, 'result[3] = 1096.6331...'); + } +} + diff --git a/src/tests/operators/math/exp/exp_i32_test.cairo b/src/tests/operators/math/exp/exp_i32_test.cairo new file mode 100644 index 000000000..cabeee1d9 --- /dev/null +++ b/src/tests/operators/math/exp/exp_i32_test.cairo @@ -0,0 +1,79 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = i32_tensor_1x3_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = i32_tensor_2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 1316288, 'result[3] = 20.085...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 1316288, 'result[3] = 20.085...'); + assert((*result.at(4).mag).into() == 3577984, 'result[3] = 54.5981...'); + assert((*result.at(5).mag).into() == 9726080, 'result[3] = 148.4131...'); + assert((*result.at(6).mag).into() == 26437888, 'result[3] = 403.4287...'); + assert((*result.at(7).mag).into() == 71866368, 'result[3] = 1096.6331...'); + } +} + diff --git a/src/tests/operators/math/exp/exp_u32_test.cairo b/src/tests/operators/math/exp/exp_u32_test.cairo new file mode 100644 index 000000000..cabeee1d9 --- /dev/null +++ b/src/tests/operators/math/exp/exp_u32_test.cairo @@ -0,0 +1,79 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = i32_tensor_1x3_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = i32_tensor_2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 1316288, 'result[3] = 20.085...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 1316288, 'result[3] = 20.085...'); + assert((*result.at(4).mag).into() == 3577984, 'result[3] = 54.5981...'); + assert((*result.at(5).mag).into() == 9726080, 'result[3] = 148.4131...'); + assert((*result.at(6).mag).into() == 26437888, 'result[3] = 403.4287...'); + assert((*result.at(7).mag).into() == 71866368, 'result[3] = 1096.6331...'); + } +} + diff --git a/src/tests/operators/math/exp_test.cairo b/src/tests/operators/math/exp_test.cairo deleted file mode 100644 index 5952de07a..000000000 --- a/src/tests/operators/math/exp_test.cairo +++ /dev/null @@ -1,19 +0,0 @@ -use array::SpanTrait; -use traits::Into; - -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::operators::tensor::core::{TensorTrait, }; -use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; -use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; - -#[test] -#[available_gas(20000000)] -fn tensor_exp_test() { - let tensor = i32_tensor_2x2_helper(); - let result = tensor.exp().data; - - assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); - assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); - assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); - assert((*result.at(3).mag).into() == 1316288, 'result[3] = 20.085...'); -} From 7b01f8478835b448ceecc2e7acf265032c66be4b Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 12:12:13 +0300 Subject: [PATCH 028/126] refactor tensor ln tests --- src/tests/operators/math.cairo | 2 +- src/tests/operators/math/ln.cairo | 3 + src/tests/operators/math/ln/ln_fp_test.cairo | 2 + .../math/ln/ln_fp_test/ln_fp16x16_test.cairo | 119 +++++++++++++++++ .../math/ln/ln_fp_test/ln_fp8x23_test.cairo | 120 ++++++++++++++++++ src/tests/operators/math/ln/ln_i32_test.cairo | 113 +++++++++++++++++ src/tests/operators/math/ln/ln_u32_test.cairo | 110 ++++++++++++++++ src/tests/operators/math/ln_test.cairo | 36 ------ 8 files changed, 468 insertions(+), 37 deletions(-) create mode 100644 src/tests/operators/math/ln.cairo create mode 100644 src/tests/operators/math/ln/ln_fp_test.cairo create mode 100644 src/tests/operators/math/ln/ln_fp_test/ln_fp16x16_test.cairo create mode 100644 src/tests/operators/math/ln/ln_fp_test/ln_fp8x23_test.cairo create mode 100644 src/tests/operators/math/ln/ln_i32_test.cairo create mode 100644 src/tests/operators/math/ln/ln_u32_test.cairo delete mode 100644 src/tests/operators/math/ln_test.cairo diff --git a/src/tests/operators/math.cairo b/src/tests/operators/math.cairo index cb5d99ec6..0fa0f68e6 100644 --- a/src/tests/operators/math.cairo +++ b/src/tests/operators/math.cairo @@ -11,4 +11,4 @@ mod less; mod less_equal; mod abs; mod ceil; -mod ln_test; +mod ln; diff --git a/src/tests/operators/math/ln.cairo b/src/tests/operators/math/ln.cairo new file mode 100644 index 000000000..a60cb374b --- /dev/null +++ b/src/tests/operators/math/ln.cairo @@ -0,0 +1,3 @@ +mod ln_u32_test; +mod ln_i32_test; +mod ln_fp_test; \ No newline at end of file diff --git a/src/tests/operators/math/ln/ln_fp_test.cairo b/src/tests/operators/math/ln/ln_fp_test.cairo new file mode 100644 index 000000000..628ffb6cf --- /dev/null +++ b/src/tests/operators/math/ln/ln_fp_test.cairo @@ -0,0 +1,2 @@ +mod ln_fp16x16_test; +mod ln_fp8x23_test; \ No newline at end of file diff --git a/src/tests/operators/math/ln/ln_fp_test/ln_fp16x16_test.cairo b/src/tests/operators/math/ln/ln_fp_test/ln_fp16x16_test.cairo new file mode 100644 index 000000000..c945b6cff --- /dev/null +++ b/src/tests/operators/math/ln/ln_fp_test/ln_fp16x16_test.cairo @@ -0,0 +1,119 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_16x16::FP16x16Impl + }; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_16x16::FP16x16Impl + }; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType}, implementations::impl_16x16::FP16x16Impl + }; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + assert((*result.at(4).mag).into() == 71992, 'result[4] = 1.0986'); + assert((*result.at(5).mag).into() == 301793, 'result[5] = 4.60517'); + assert((*result.at(6).mag).into() == 71992, 'result[6] = 1.0986'); + assert((*result.at(7).mag).into() == 301793, 'result[7] = 4.60517'); + } +} + diff --git a/src/tests/operators/math/ln/ln_fp_test/ln_fp8x23_test.cairo b/src/tests/operators/math/ln/ln_fp_test/ln_fp8x23_test.cairo new file mode 100644 index 000000000..fed6f7438 --- /dev/null +++ b/src/tests/operators/math/ln/ln_fp_test/ln_fp8x23_test.cairo @@ -0,0 +1,120 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType, FixedImpl}, implementations::impl_8x23::FP8x23Impl + }; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + use debug::PrintTrait; + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 5814556, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 9215831, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 38630976, 'result[3] = 4.60517'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType, FixedImpl}, implementations::impl_8x23::FP8x23Impl + }; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 5814556, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 9215831, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 38630976, 'result[3] = 4.60517'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::numbers::fixed_point::{ + core::{FixedTrait, FixedType, FixedImpl}, implementations::impl_8x23::FP8x23Impl + }; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(1, false)); + data.append(FixedTrait::new_unscaled(2, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(3, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 5814556, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 9215831, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 38630976, 'result[3] = 4.60517'); + assert((*result.at(4).mag).into() == 9215831, 'result[4] = 1.0986'); + assert((*result.at(5).mag).into() == 38630976, 'result[5] = 4.60517'); + assert((*result.at(6).mag).into() == 9215831, 'result[6] = 1.0986'); + assert((*result.at(7).mag).into() == 38630976, 'result[7] = 4.60517'); + } +} + diff --git a/src/tests/operators/math/ln/ln_i32_test.cairo b/src/tests/operators/math/ln/ln_i32_test.cairo new file mode 100644 index 000000000..d8e65b020 --- /dev/null +++ b/src/tests/operators/math/ln/ln_i32_test.cairo @@ -0,0 +1,113 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + assert((*result.at(4).mag).into() == 71992, 'result[4] = 1.0986'); + assert((*result.at(5).mag).into() == 301793, 'result[5] = 4.60517'); + assert((*result.at(6).mag).into() == 71992, 'result[6] = 1.0986'); + assert((*result.at(7).mag).into() == 301793, 'result[7] = 4.60517'); + } +} + diff --git a/src/tests/operators/math/ln/ln_u32_test.cairo b/src/tests/operators/math/ln/ln_u32_test.cairo new file mode 100644 index 000000000..5b57d6ac8 --- /dev/null +++ b/src/tests/operators/math/ln/ln_u32_test.cairo @@ -0,0 +1,110 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(1); + data.append(2); + data.append(3); + data.append(100); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(1); + data.append(2); + data.append(3); + data.append(100); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_ln_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(1); + data.append(2); + data.append(3); + data.append(100); + data.append(3); + data.append(100); + data.append(3); + data.append(100); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.ln().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); + assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); + assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); + assert((*result.at(4).mag).into() == 71992, 'result[4] = 1.0986'); + assert((*result.at(5).mag).into() == 301793, 'result[5] = 4.60517'); + assert((*result.at(6).mag).into() == 71992, 'result[6] = 1.0986'); + assert((*result.at(7).mag).into() == 301793, 'result[7] = 4.60517'); + } +} + diff --git a/src/tests/operators/math/ln_test.cairo b/src/tests/operators/math/ln_test.cairo deleted file mode 100644 index fcd34d77b..000000000 --- a/src/tests/operators/math/ln_test.cairo +++ /dev/null @@ -1,36 +0,0 @@ -use array::SpanTrait; -use traits::Into; -use array::ArrayTrait; - -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; - -use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; -use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; - -#[test] -#[available_gas(20000000)] -fn ln_test() { - let mut sizes = ArrayTrait::new(); - sizes.append(4); - - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(1, false)); - data.append(IntegerTrait::new(2, false)); - data.append(IntegerTrait::new(3, false)); - data.append(IntegerTrait::new(100, false)); - let extra = Option::::None(()); - - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); - - - let result = tensor.ln().data; - - assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); - assert((*result.at(1).mag).into() == 45355, 'result[1] = 0.69315'); - assert((*result.at(2).mag).into() == 71992, 'result[2] = 1.0986'); - assert((*result.at(3).mag).into() == 301793, 'result[3] = 4.60517'); -} - - From a9fe76235ab4e95bd15fe190efbd3b4f98d8d743 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 12:25:40 +0300 Subject: [PATCH 029/126] fix extra param in tensor fp8x23 --- .../argmax_fp_test/argmax_fp8x23_test.cairo | 30 ++--- .../argmin_fp_test/argmin_fp8x23_test.cairo | 110 ++++++++---------- .../equal_fp_test/equal_fp8x23_test.cairo | 56 ++++++--- .../greater_fp_test/greater_fp8x23_test.cairo | 36 +++--- .../greater_equal_fp8x23_test.cairo | 56 ++++++--- .../less/less_fp_test/less_fp8x23_test.cairo | 36 +++--- .../less_equal_fp8x23_test.cairo | 56 ++++++--- 7 files changed, 211 insertions(+), 169 deletions(-) diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo index d6b40125e..020727d37 100644 --- a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo +++ b/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo @@ -2,7 +2,7 @@ #[cfg(test)] mod tensor_1D { use array::{ArrayTrait,SpanTrait}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -23,9 +23,9 @@ mod tensor_1D { data.append(FixedTrait::new(0, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::None(()),Option::None(())); assert(*result.data.at(0) == 2, 'result[0] = 2'); @@ -37,9 +37,9 @@ mod tensor_1D { data.append(FixedTrait::new(0, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::None(()),Option::None(())); assert(*result.data.at(0) == 1, 'result[0] = 1'); @@ -65,9 +65,9 @@ mod tensor_1D { data.append(FixedTrait::new(0, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::Some(false),Option::None(())); assert(*result.data.at(0) == 1, 'result[0] = 1'); @@ -90,9 +90,9 @@ mod tensor_1D { data.append(FixedTrait::new(1, true)); data.append(FixedTrait::new(1, true)); data.append(FixedTrait::new(1, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); assert(*result.data.at(0) == 0, 'result[0] = 0'); @@ -113,7 +113,7 @@ mod tensor_1D { #[cfg(test)] mod tensor_2D { use array::{ArrayTrait,SpanTrait}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -179,8 +179,8 @@ mod tensor_2D { data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(1, false)); - let extra = Option::::None(()); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(1,Option::None(()),Option::Some(false)); assert(*result.data.at(0) == 0, 'result[0] = 0'); @@ -203,7 +203,7 @@ mod tensor_2D { #[cfg(test)] mod tensor_3D { use array::{ArrayTrait,SpanTrait}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -291,8 +291,8 @@ mod tensor_3D { data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(1, false)); - let extra = Option::::None(()); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo index da5c1ad26..8f8e7c4bf 100644 --- a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo +++ b/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo @@ -1,8 +1,7 @@ - #[cfg(test)] mod tensor_1D { - use array::{ArrayTrait,SpanTrait}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use array::{ArrayTrait, SpanTrait}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; @@ -10,7 +9,6 @@ mod tensor_1D { #[test] #[available_gas(20000000)] fn default_parameters() { - //////////////////////////////////////////// // case: default parameters //////////////////////////////////////////// @@ -22,29 +20,27 @@ mod tensor_1D { data.append(FixedTrait::new(0, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = tensor.argmin(0,Option::None(()),Option::None(())); + let result = tensor.argmin(0, Option::None(()), Option::None(())); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); - let mut data = ArrayTrait::new(); data.append(FixedTrait::new(0, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = tensor.argmin(0,Option::None(()),Option::None(())); + let result = tensor.argmin(0, Option::None(()), Option::None(())); assert(*result.data.at(0) == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); - } #[test] @@ -64,11 +60,11 @@ mod tensor_1D { data.append(FixedTrait::new(0, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = tensor.argmin(0,Option::Some(false),Option::None(())); + let result = tensor.argmin(0, Option::Some(false), Option::None(())); assert(*result.data.at(0) == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -77,7 +73,6 @@ mod tensor_1D { #[test] #[available_gas(20000000)] fn select_last_index() { - //////////////////////////////////////////// // case: select_last_index == false //////////////////////////////////////////// @@ -89,11 +84,11 @@ mod tensor_1D { data.append(FixedTrait::new(1, true)); data.append(FixedTrait::new(1, true)); data.append(FixedTrait::new(1, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = tensor.argmin(0,Option::None(()),Option::Some(false)); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = tensor.argmin(0, Option::None(()), Option::Some(false)); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -102,16 +97,15 @@ mod tensor_1D { // case: select_last_index == true //////////////////////////////////////////// - let mut data = ArrayTrait::new(); data.append(FixedTrait::new(1, true)); data.append(FixedTrait::new(1, true)); data.append(FixedTrait::new(1, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); - let result = tensor.argmin(0,Option::None(()),Option::Some(true)); + let result = tensor.argmin(0, Option::None(()), Option::Some(true)); assert(*result.data.at(0) == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -120,13 +114,13 @@ mod tensor_1D { #[cfg(test)] mod tensor_2D { - use array::{ArrayTrait,SpanTrait}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use array::{ArrayTrait, SpanTrait}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::helpers::tensor::fixed_point::fp8x23::{ - fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper + fp_tensor_1x3_helper, fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; #[test] @@ -138,43 +132,37 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); - let result = tensor.argmin(0,Option::None(()),Option::None(())); + let result = tensor.argmin(0, Option::None(()), Option::None(())); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); - - let result = tensor.argmin(1,Option::None(()),Option::None(())); + let result = tensor.argmin(1, Option::None(()), Option::None(())); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); - - } #[test] #[available_gas(20000000)] fn keepdims() { - //////////////////////////////////////////// // case: keepdims == false //////////////////////////////////////////// let tensor = fp_tensor_2x2_helper(); - let result = tensor.argmin(1,Option::Some(false),Option::None(())); + let result = tensor.argmin(1, Option::Some(false), Option::None(())); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); - } #[test] #[available_gas(20000000)] fn select_last_index() { - //////////////////////////////////////////// // case: select_last_index == false //////////////////////////////////////////// @@ -187,10 +175,10 @@ mod tensor_2D { data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(1, false)); - let extra = Option::::None(()); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); - let result = tensor.argmin(1,Option::None(()),Option::Some(false)); + let result = tensor.argmin(1, Option::None(()), Option::Some(false)); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); @@ -208,10 +196,10 @@ mod tensor_2D { data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(1, false)); - let extra = Option::::None(()); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); - let result = tensor.argmin(1,Option::None(()),Option::Some(true)); + let result = tensor.argmin(1, Option::None(()), Option::Some(true)); assert(*result.data.at(0) == 1, 'result[0] = 1'); assert(*result.data.at(1) == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); @@ -221,13 +209,13 @@ mod tensor_2D { #[cfg(test)] mod tensor_3D { - use array::{ArrayTrait,SpanTrait}; - use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use array::{ArrayTrait, SpanTrait}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; use orion::tests::helpers::tensor::fixed_point::fp8x23::{ - fp_tensor_1x3_helper,fp_tensor_2x2_helper, fp_tensor_2x2x2_helper + fp_tensor_1x3_helper, fp_tensor_2x2_helper, fp_tensor_2x2x2_helper }; #[test] @@ -238,7 +226,7 @@ mod tensor_3D { //////////////////////////////////////////// let tensor = fp_tensor_2x2x2_helper(); - let result = tensor.argmin(0,Option::None(()),Option::None(())); + let result = tensor.argmin(0, Option::None(()), Option::None(())); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); @@ -247,8 +235,7 @@ mod tensor_3D { assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); - - let result = tensor.argmin(1,Option::None(()),Option::None(())); + let result = tensor.argmin(1, Option::None(()), Option::None(())); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); @@ -257,8 +244,7 @@ mod tensor_3D { assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); - - let result = tensor.argmin(2,Option::None(()),Option::None(())); + let result = tensor.argmin(2, Option::None(()), Option::None(())); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); @@ -272,13 +258,12 @@ mod tensor_3D { #[test] #[available_gas(20000000)] fn keepdims() { - //////////////////////////////////////////// // case: keepdims == false //////////////////////////////////////////// let tensor = fp_tensor_2x2x2_helper(); - let result = tensor.argmin(0,Option::Some(false),Option::None(())); + let result = tensor.argmin(0, Option::Some(false), Option::None(())); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); assert(*result.data.at(2) == 0, 'result[2] = 0'); @@ -290,7 +275,6 @@ mod tensor_3D { #[test] #[available_gas(20000000)] fn select_last_index() { - //////////////////////////////////////////// // case: select_last_index == false //////////////////////////////////////////// @@ -309,9 +293,9 @@ mod tensor_3D { data.append(FixedTrait::new(1, false)); data.append(FixedTrait::new(1, false)); - let extra = Option::::None(()); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); - let result = tensor.argmin(0,Option::None(()),Option::Some(false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + let result = tensor.argmin(0, Option::None(()), Option::Some(false)); assert(*result.data.at(0) == 0, 'result[0] = 0'); assert(*result.data.at(1) == 0, 'result[1] = 0'); assert(*result.data.at(2) == 0, 'result[2] = 0'); @@ -319,15 +303,13 @@ mod tensor_3D { assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); - //////////////////////////////////////////// // case: select_last_index == true //////////////////////////////////////////// - - let extra = Option::::None(()); - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); - let result = tensor.argmin(0,Option::None(()),Option::Some(true)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + let result = tensor.argmin(0, Option::None(()), Option::Some(true)); assert(*result.data.at(0) == 1, 'result[0] = 1'); assert(*result.data.at(1) == 1, 'result[1] = 1'); assert(*result.data.at(2) == 1, 'result[2] = 1'); diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo b/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo index 79ea79852..a824347c7 100644 --- a/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo +++ b/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo @@ -7,7 +7,7 @@ mod tensor_1D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] @@ -26,10 +26,14 @@ mod tensor_1D { arr_2.append(FixedTrait::new_unscaled(11, false)); arr_2.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result = tensor_a.eq(@tensor_b); assert(*result.data.at(0) == 0, 'result[0] = 0'); @@ -50,7 +54,7 @@ mod tensor_2D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; @@ -83,10 +87,14 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(17, false)); arr_2.append(FixedTrait::new_unscaled(18, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result = tensor_a.eq(@tensor_b); assert(*result.data.at(0) == 0, 'result[0] = 0'); @@ -132,10 +140,14 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(1, false)); arr_2.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes_1.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes_2.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_b.eq(@tensor_a); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -178,7 +190,7 @@ mod tensor_3D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] @@ -209,10 +221,14 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(16, false)); arr_2.append(FixedTrait::new_unscaled(17, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result = tensor_a.eq(@tensor_b); assert(*result.data.at(0) == 0, 'result[0] = 0'); @@ -254,10 +270,14 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(0, false)); arr_2.append(FixedTrait::new_unscaled(1, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes_1.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes_2.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_b.eq(@tensor_a); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo b/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo index 413f7c24b..4cdead3dd 100644 --- a/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo +++ b/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo @@ -7,7 +7,7 @@ mod tensor_1D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] @@ -26,10 +26,10 @@ mod tensor_1D { arr_2.append(FixedTrait::new_unscaled(11, false)); arr_2.append(FixedTrait::new_unscaled(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.greater(@tensor_b); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); @@ -50,7 +50,7 @@ mod tensor_2D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] @@ -82,10 +82,10 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(17, false)); arr_2.append(FixedTrait::new_unscaled(18, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.greater(@tensor_b); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); @@ -144,10 +144,10 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(1, false)); arr_2.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_b.greater(@tensor_a); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); @@ -193,7 +193,7 @@ mod tensor_3D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] @@ -224,10 +224,10 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(16, false)); arr_2.append(FixedTrait::new_unscaled(17, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.greater(@tensor_b); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); @@ -281,10 +281,10 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(0, false)); arr_2.append(FixedTrait::new_unscaled(1, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_b.greater(@tensor_a); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); diff --git a/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo b/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo index ee0588820..f51426d7f 100644 --- a/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo +++ b/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo @@ -7,7 +7,7 @@ mod tensor_1D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::{ - core::{FixedTrait, FixedType}, implementations::impl_8x23::FP8x23Impl + core::{FixedTrait, FixedType, FixedImpl}, implementations::impl_8x23::FP8x23Impl }; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; @@ -27,10 +27,14 @@ mod tensor_1D { arr_2.append(FixedTrait::new_unscaled(11, false)); arr_2.append(FixedTrait::new_unscaled(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_a.greater_equal(@tensor_b); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); @@ -51,7 +55,7 @@ mod tensor_2D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::{ - core::{FixedTrait, FixedType}, implementations::impl_8x23::FP8x23Impl + core::{FixedTrait, FixedType, FixedImpl}, implementations::impl_8x23::FP8x23Impl }; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; @@ -85,10 +89,14 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(17, false)); arr_2.append(FixedTrait::new_unscaled(18, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_a.greater_equal(@tensor_b); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); @@ -147,10 +155,14 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(1, false)); arr_2.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes_1.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes_2.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_b.greater_equal(@tensor_a); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -196,7 +208,7 @@ mod tensor_3D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::numbers::fixed_point::{ - core::{FixedTrait, FixedType}, implementations::impl_8x23::FP8x23Impl + core::{FixedTrait, FixedType, FixedImpl}, implementations::impl_8x23::FP8x23Impl }; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; @@ -228,10 +240,14 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(16, false)); arr_2.append(FixedTrait::new_unscaled(17, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_a.greater_equal(@tensor_b); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); @@ -285,10 +301,14 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(0, false)); arr_2.append(FixedTrait::new_unscaled(1, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes_1.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes_2.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_b.greater_equal(@tensor_a); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); diff --git a/src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo b/src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo index acbaff4b9..9efe3284e 100644 --- a/src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo +++ b/src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo @@ -7,7 +7,7 @@ mod tensor_1D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] @@ -26,10 +26,10 @@ mod tensor_1D { arr_2.append(FixedTrait::new_unscaled(11, false)); arr_2.append(FixedTrait::new_unscaled(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.less(@tensor_b); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -49,7 +49,7 @@ mod tensor_2D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; @@ -82,10 +82,10 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(17, false)); arr_2.append(FixedTrait::new_unscaled(18, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.less(@tensor_b); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -144,10 +144,10 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(1, false)); arr_2.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_b.less(@tensor_a); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); @@ -192,7 +192,7 @@ mod tensor_3D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; @@ -224,10 +224,10 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(16, false)); arr_2.append(FixedTrait::new_unscaled(17, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.less(@tensor_b); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -281,10 +281,10 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(0, false)); arr_2.append(FixedTrait::new_unscaled(1, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), Option::Some(extra)); + let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_b.less(@tensor_a); assert(*result_a.data.at(0) == 0, 'result[0] = 0'); diff --git a/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo b/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo index c9456396a..b4b8ff3f5 100644 --- a/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo +++ b/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo @@ -7,7 +7,7 @@ mod tensor_1D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] @@ -26,10 +26,14 @@ mod tensor_1D { arr_2.append(FixedTrait::new_unscaled(11, false)); arr_2.append(FixedTrait::new_unscaled(2, true)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_a.less_equal(@tensor_b); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -50,7 +54,7 @@ mod tensor_2D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; @@ -83,10 +87,14 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(17, false)); arr_2.append(FixedTrait::new_unscaled(18, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_a.less_equal(@tensor_b); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -145,10 +153,14 @@ mod tensor_2D { arr_2.append(FixedTrait::new_unscaled(1, false)); arr_2.append(FixedTrait::new_unscaled(2, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes_1.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes_2.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_b.less_equal(@tensor_a); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -194,7 +206,7 @@ mod tensor_3D { use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; use orion::operators::tensor::core::{TensorTrait, ExtraParams}; - use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; #[test] @@ -225,10 +237,14 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(16, false)); arr_2.append(FixedTrait::new_unscaled(17, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_a.less_equal(@tensor_b); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); @@ -282,10 +298,14 @@ mod tensor_3D { arr_2.append(FixedTrait::new_unscaled(0, false)); arr_2.append(FixedTrait::new_unscaled(1, false)); - let extra = Option::::None(()); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor_a = TensorTrait::::new(sizes_1.span(), arr_1.span(), extra); - let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); + let tensor_a = TensorTrait::::new( + sizes_1.span(), arr_1.span(), Option::Some(extra) + ); + let tensor_b = TensorTrait::::new( + sizes_2.span(), arr_2.span(), Option::Some(extra) + ); let result_a = tensor_b.less_equal(@tensor_a); assert(*result_a.data.at(0) == 1, 'result[0] = 1'); From b546fb79fa24c8162aa41ca8f173b6727f205adb Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 12:38:32 +0300 Subject: [PATCH 030/126] refactor tensor max tests --- src/tests/operators/math.cairo | 2 +- src/tests/operators/math/max.cairo | 3 + .../operators/math/max/max_fp_test.cairo | 2 + .../max/max_fp_test/max_fp16x16_test.cairo | 62 +++++++++++++++++++ .../max/max_fp_test/max_fp8x23_test.cairo | 62 +++++++++++++++++++ .../operators/math/max/max_i32_test.cairo | 54 ++++++++++++++++ .../operators/math/max/max_u32_test.cairo | 54 ++++++++++++++++ src/tests/operators/math/max_test.cairo | 12 ---- 8 files changed, 238 insertions(+), 13 deletions(-) create mode 100644 src/tests/operators/math/max.cairo create mode 100644 src/tests/operators/math/max/max_fp_test.cairo create mode 100644 src/tests/operators/math/max/max_fp_test/max_fp16x16_test.cairo create mode 100644 src/tests/operators/math/max/max_fp_test/max_fp8x23_test.cairo create mode 100644 src/tests/operators/math/max/max_i32_test.cairo create mode 100644 src/tests/operators/math/max/max_u32_test.cairo delete mode 100644 src/tests/operators/math/max_test.cairo diff --git a/src/tests/operators/math.cairo b/src/tests/operators/math.cairo index 0fa0f68e6..15bc3297d 100644 --- a/src/tests/operators/math.cairo +++ b/src/tests/operators/math.cairo @@ -1,6 +1,6 @@ mod argmax; mod argmin; -mod max_test; +mod max; mod min_test; mod reduce_sum_test; mod exp; diff --git a/src/tests/operators/math/max.cairo b/src/tests/operators/math/max.cairo new file mode 100644 index 000000000..6dbfabe36 --- /dev/null +++ b/src/tests/operators/math/max.cairo @@ -0,0 +1,3 @@ +mod max_u32_test; +mod max_i32_test; +mod max_fp_test; \ No newline at end of file diff --git a/src/tests/operators/math/max/max_fp_test.cairo b/src/tests/operators/math/max/max_fp_test.cairo new file mode 100644 index 000000000..e5ef96043 --- /dev/null +++ b/src/tests/operators/math/max/max_fp_test.cairo @@ -0,0 +1,2 @@ +mod max_fp8x23_test; +mod max_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/math/max/max_fp_test/max_fp16x16_test.cairo b/src/tests/operators/math/max/max_fp_test/max_fp16x16_test.cairo new file mode 100644 index 000000000..0a95a8e22 --- /dev/null +++ b/src/tests/operators/math/max/max_fp_test/max_fp16x16_test.cairo @@ -0,0 +1,62 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.max().mag; + assert(result == FixedTrait::new_unscaled(2, false).mag, 'tensor.max = 2'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.max().mag; + assert(result == FixedTrait::new_unscaled(3, false).mag, 'tensor.max = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.max().mag; + assert(result == FixedTrait::new_unscaled(7, false).mag, 'tensor.max = 7'); + } +} + diff --git a/src/tests/operators/math/max/max_fp_test/max_fp8x23_test.cairo b/src/tests/operators/math/max/max_fp_test/max_fp8x23_test.cairo new file mode 100644 index 000000000..7fc0f2550 --- /dev/null +++ b/src/tests/operators/math/max/max_fp_test/max_fp8x23_test.cairo @@ -0,0 +1,62 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.max().mag; + assert(result == FixedTrait::new_unscaled(2, false).mag, 'tensor.max = 2'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.max().mag; + assert(result == FixedTrait::new_unscaled(3, false).mag, 'tensor.max = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.max().mag; + assert(result == FixedTrait::new_unscaled(7, false).mag, 'tensor.max = 7'); + } +} + diff --git a/src/tests/operators/math/max/max_i32_test.cairo b/src/tests/operators/math/max/max_i32_test.cairo new file mode 100644 index 000000000..9d714d4c4 --- /dev/null +++ b/src/tests/operators/math/max/max_i32_test.cairo @@ -0,0 +1,54 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = i32_tensor_1x3_helper(); + + let result = tensor.max().mag; + assert(result == 2, 'tensor.max = 2'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = i32_tensor_2x2_helper(); + + let result = tensor.max().mag; + assert(result == 3, 'tensor.max = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.max().mag; + assert(result == 7, 'tensor.max = 7'); + } +} + diff --git a/src/tests/operators/math/max/max_u32_test.cairo b/src/tests/operators/math/max/max_u32_test.cairo new file mode 100644 index 000000000..292b0773e --- /dev/null +++ b/src/tests/operators/math/max/max_u32_test.cairo @@ -0,0 +1,54 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = u32_tensor_1x3_helper(); + + let result = tensor.max(); + assert(result == 2, 'tensor.max = 2'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = u32_tensor_2x2_helper(); + + let result = tensor.max(); + assert(result == 3, 'tensor.max = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_max() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.max(); + assert(result == 7, 'tensor.max = 7'); + } +} + diff --git a/src/tests/operators/math/max_test.cairo b/src/tests/operators/math/max_test.cairo deleted file mode 100644 index d277ad9fd..000000000 --- a/src/tests/operators/math/max_test.cairo +++ /dev/null @@ -1,12 +0,0 @@ -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::operators::tensor::core::TensorTrait; -use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; - -#[test] -#[available_gas(2000000)] -fn max_tensor() { - let tensor = i32_tensor_2x2x2_helper(); - - let result = tensor.max().mag; - assert(result == 7, 'tensor.max = 7'); -} From 964bf187fce137786430e63afa251c42f88e2aa8 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 12:42:51 +0300 Subject: [PATCH 031/126] refactor tensor min tests --- src/tests/operators/math.cairo | 2 +- src/tests/operators/math/min.cairo | 3 + .../operators/math/min/min_fp_test.cairo | 2 + .../min/min_fp_test/min_fp16x16_test.cairo | 62 +++++++++++++++++++ .../min/min_fp_test/min_fp8x23_test.cairo | 62 +++++++++++++++++++ .../operators/math/min/min_i32_test.cairo | 54 ++++++++++++++++ .../operators/math/min/min_u32_test.cairo | 54 ++++++++++++++++ src/tests/operators/math/min_test.cairo | 12 ---- 8 files changed, 238 insertions(+), 13 deletions(-) create mode 100644 src/tests/operators/math/min.cairo create mode 100644 src/tests/operators/math/min/min_fp_test.cairo create mode 100644 src/tests/operators/math/min/min_fp_test/min_fp16x16_test.cairo create mode 100644 src/tests/operators/math/min/min_fp_test/min_fp8x23_test.cairo create mode 100644 src/tests/operators/math/min/min_i32_test.cairo create mode 100644 src/tests/operators/math/min/min_u32_test.cairo delete mode 100644 src/tests/operators/math/min_test.cairo diff --git a/src/tests/operators/math.cairo b/src/tests/operators/math.cairo index 15bc3297d..c11b183be 100644 --- a/src/tests/operators/math.cairo +++ b/src/tests/operators/math.cairo @@ -1,7 +1,7 @@ mod argmax; mod argmin; mod max; -mod min_test; +mod min; mod reduce_sum_test; mod exp; mod equal; diff --git a/src/tests/operators/math/min.cairo b/src/tests/operators/math/min.cairo new file mode 100644 index 000000000..9b3d49b66 --- /dev/null +++ b/src/tests/operators/math/min.cairo @@ -0,0 +1,3 @@ +mod min_u32_test; +mod min_i32_test; +mod min_fp_test; \ No newline at end of file diff --git a/src/tests/operators/math/min/min_fp_test.cairo b/src/tests/operators/math/min/min_fp_test.cairo new file mode 100644 index 000000000..e5ad01dfe --- /dev/null +++ b/src/tests/operators/math/min/min_fp_test.cairo @@ -0,0 +1,2 @@ +mod min_fp8x23_test; +mod min_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/math/min/min_fp_test/min_fp16x16_test.cairo b/src/tests/operators/math/min/min_fp_test/min_fp16x16_test.cairo new file mode 100644 index 000000000..4d3b72cee --- /dev/null +++ b/src/tests/operators/math/min/min_fp_test/min_fp16x16_test.cairo @@ -0,0 +1,62 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + diff --git a/src/tests/operators/math/min/min_fp_test/min_fp8x23_test.cairo b/src/tests/operators/math/min/min_fp_test/min_fp8x23_test.cairo new file mode 100644 index 000000000..7c04f1720 --- /dev/null +++ b/src/tests/operators/math/min/min_fp_test/min_fp8x23_test.cairo @@ -0,0 +1,62 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + use orion::numbers::fixed_point::core::{FixedTrait}; + + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + diff --git a/src/tests/operators/math/min/min_i32_test.cairo b/src/tests/operators/math/min/min_i32_test.cairo new file mode 100644 index 000000000..59cefae7c --- /dev/null +++ b/src/tests/operators/math/min/min_i32_test.cairo @@ -0,0 +1,54 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = i32_tensor_1x3_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = i32_tensor_2x2_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.min().mag; + assert(result == 0, 'tensor.min = 0'); + } +} + diff --git a/src/tests/operators/math/min/min_u32_test.cairo b/src/tests/operators/math/min/min_u32_test.cairo new file mode 100644 index 000000000..e7155a943 --- /dev/null +++ b/src/tests/operators/math/min/min_u32_test.cairo @@ -0,0 +1,54 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = u32_tensor_1x3_helper(); + + let result = tensor.min(); + assert(result == 0, 'tensor.min = 0'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = u32_tensor_2x2_helper(); + + let result = tensor.min(); + assert(result == 0, 'tensor.min = 0'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(2000000)] + fn tensor_min() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.min(); + assert(result == 0, 'tensor.min = 0'); + } +} + diff --git a/src/tests/operators/math/min_test.cairo b/src/tests/operators/math/min_test.cairo deleted file mode 100644 index dea3e0897..000000000 --- a/src/tests/operators/math/min_test.cairo +++ /dev/null @@ -1,12 +0,0 @@ -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::operators::tensor::core::TensorTrait; -use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; - -#[test] -#[available_gas(2000000)] -fn min_tensor() { - let tensor = i32_tensor_2x2x2_helper(); - - let result = tensor.min().mag; - assert(result == 0, 'tensor.min = 0'); -} From 5cac0cc4e54676d9fdad54b8e5d9dbb6fd7ebdaf Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 14:46:09 +0300 Subject: [PATCH 032/126] refactor reduce_sum tests --- .../reduce_sum/reduce_sum_fp/fp16x16.cairo | 3 +- .../reduce_sum/reduce_sum_fp/fp8x23.cairo | 3 +- .../math/reduce_sum/reduce_sum_i32.cairo | 3 +- .../math/reduce_sum/reduce_sum_u32.cairo | 3 +- src/tests/operators/math.cairo | 2 +- src/tests/operators/math/reduce_sum.cairo | 3 + .../math/reduce_sum/reduce_sum_fp_test.cairo | 2 + .../reduce_sum_fp16x16_test.cairo | 242 ++++++++++++++++++ .../reduce_sum_fp8x23_test.cairo | 242 ++++++++++++++++++ .../math/reduce_sum/reduce_sum_i32_test.cairo | 228 +++++++++++++++++ .../math/reduce_sum/reduce_sum_u32_test.cairo | 228 +++++++++++++++++ .../operators/math/reduce_sum_test.cairo | 45 ---- 12 files changed, 954 insertions(+), 50 deletions(-) create mode 100644 src/tests/operators/math/reduce_sum.cairo create mode 100644 src/tests/operators/math/reduce_sum/reduce_sum_fp_test.cairo create mode 100644 src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo create mode 100644 src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo create mode 100644 src/tests/operators/math/reduce_sum/reduce_sum_i32_test.cairo create mode 100644 src/tests/operators/math/reduce_sum/reduce_sum_u32_test.cairo delete mode 100644 src/tests/operators/math/reduce_sum_test.cairo diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo index 0032287b9..bdcbc295e 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo @@ -12,10 +12,10 @@ use orion::utils::check_gas; /// Cf: TensorTrait::reduce_sum docstring fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { - assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let mut output_data = ArrayTrait::new(); if (*self.shape).len() == 1 { + assert(axis == 0, 'axis out of dimensions'); let current_sum = accumulate_sum(*self.data, *self.shape, *self.shape, axis); output_data.append(current_sum); @@ -24,6 +24,7 @@ fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor::new(output_shape.span(), output_data.span(), *self.extra); } else { + assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); let mut index: usize = 0; diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo index c2087b279..58c649291 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo @@ -12,10 +12,10 @@ use orion::utils::check_gas; /// Cf: TensorTrait::reduce_sum docstring fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { - assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let mut output_data = ArrayTrait::new(); if (*self.shape).len() == 1 { + assert(axis == 0, 'axis out of dimensions'); let current_sum = accumulate_sum(*self.data, *self.shape, *self.shape, axis); output_data.append(current_sum); @@ -24,6 +24,7 @@ fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor::new(output_shape.span(), output_data.span(), *self.extra); } else { + assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); let mut index: usize = 0; diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo index 27ff5e8f2..1d2fb803e 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo @@ -10,10 +10,10 @@ use orion::utils::check_gas; /// Cf: TensorTrait::reduce_sum docstring fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { - assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let mut output_data = ArrayTrait::new(); if (*self.shape).len() == 1 { + assert(axis == 0, 'axis out of dimensions'); let current_sum = accumulate_sum(*self.data, *self.shape, *self.shape, axis); output_data.append(current_sum); @@ -22,6 +22,7 @@ fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { return TensorTrait::::new(output_shape.span(), output_data.span(), *self.extra); } else { + assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); let mut index: usize = 0; diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo index 547c2f07c..4d5fa6db3 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo @@ -9,10 +9,10 @@ use orion::utils::check_gas; /// Cf: TensorTrait::reduce_sum docstring fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { - assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let mut output_data = ArrayTrait::new(); if (*self.shape).len() == 1 { + assert(axis == 0, 'axis out of dimensions'); let current_sum = accumulate_sum(*self.data, *self.shape, *self.shape, axis); output_data.append(current_sum); @@ -21,6 +21,7 @@ fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { return TensorTrait::::new(output_shape.span(), output_data.span(), *self.extra); } else { + assert(axis <= (*self.shape).len(), 'axis out of dimensions'); let output_shape = reduce_output_shape(*self.shape, axis, false); let output_data_len = len_from_shape(output_shape); let mut index: usize = 0; diff --git a/src/tests/operators/math.cairo b/src/tests/operators/math.cairo index c11b183be..8953d0ad3 100644 --- a/src/tests/operators/math.cairo +++ b/src/tests/operators/math.cairo @@ -2,7 +2,7 @@ mod argmax; mod argmin; mod max; mod min; -mod reduce_sum_test; +mod reduce_sum; mod exp; mod equal; mod greater; diff --git a/src/tests/operators/math/reduce_sum.cairo b/src/tests/operators/math/reduce_sum.cairo new file mode 100644 index 000000000..eabbef7d2 --- /dev/null +++ b/src/tests/operators/math/reduce_sum.cairo @@ -0,0 +1,3 @@ +mod reduce_sum_u32_test; +mod reduce_sum_i32_test; +mod reduce_sum_fp_test; \ No newline at end of file diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_fp_test.cairo b/src/tests/operators/math/reduce_sum/reduce_sum_fp_test.cairo new file mode 100644 index 000000000..00eb45bd8 --- /dev/null +++ b/src/tests/operators/math/reduce_sum/reduce_sum_fp_test.cairo @@ -0,0 +1,2 @@ +mod reduce_sum_fp8x23_test; +mod reduce_sum_fp16x16_test; diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo b/src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo new file mode 100644 index 000000000..db6d394f0 --- /dev/null +++ b/src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo @@ -0,0 +1,242 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Into, FP16x16Impl, FP16x16PartialEq + }; + use orion::numbers::fixed_point::core::FixedTrait; + + #[test] + #[available_gas(20000000)] + fn reduce_sum() { + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(3, false), 'result[0] = 3'); + assert(result.data.len() == 1, 'result.data.len = 1'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.reduce_sum(1, false); + } +} +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Into, FP16x16Impl, FP16x16PartialEq + }; + use orion::numbers::fixed_point::core::FixedTrait; + + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_false() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(2, false), 'result.data[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4, false), 'result.data[1] = 4'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 1, 'result.shape.len = 1'); + } + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_true() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(0, true); + + assert((*result.data[0]) == FixedTrait::new_unscaled(2, false), 'result.data[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4, false), 'result.data[1] = 4'); + assert((*result.shape[0]) == 1, 'result.shape[0] = 1'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_false() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(1, false); + + assert((*result.data[0]) == FixedTrait::new_unscaled(1, false), 'result.data[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5, false), 'result.data[1] = 5'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 1, 'result.shape.len = 1'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_true() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(1, true); + + assert((*result.data[0]) == FixedTrait::new_unscaled(1, false), 'result.data[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5, false), 'result.data[1] = 5'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 1, 'result.shape[1] = 1'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(2, false); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Into, FP16x16Impl, FP16x16PartialEq + }; + use orion::numbers::fixed_point::core::FixedTrait; + + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_false() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(4, false), 'result[0] = 4'); + assert((*result.data[1]) == FixedTrait::new_unscaled(6, false), 'result[1] = 6'); + assert((*result.data[2]) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert((*result.data[3]) == FixedTrait::new_unscaled(10, false), 'result[3] = 10'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_true() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(0, true); + assert((*result.data[0]) == FixedTrait::new_unscaled(4, false), 'result[0] = 4'); + assert((*result.data[1]) == FixedTrait::new_unscaled(6, false), 'result[1] = 6'); + assert((*result.data[2]) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert((*result.data[3]) == FixedTrait::new_unscaled(10, false), 'result[3] = 10'); + assert((*result.shape[0]) == 1, 'result.shape[0] = 1'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert((*result.shape[2]) == 2, 'result.shape[2] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_false() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(1, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert((*result.data[2]) == FixedTrait::new_unscaled(10, false), 'result[2] = 10'); + assert((*result.data[3]) == FixedTrait::new_unscaled(12, false), 'result[3] = 12'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_true() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(1, true); + assert((*result.data[0]) == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert((*result.data[2]) == FixedTrait::new_unscaled(10, false), 'result[2] = 10'); + assert((*result.data[3]) == FixedTrait::new_unscaled(12, false), 'result[3] = 12'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 1, 'result.shape[1] = 1'); + assert((*result.shape[2]) == 2, 'result.shape[2] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_2_keepdims_false() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(2, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5, false), 'result[1] = 5'); + assert((*result.data[2]) == FixedTrait::new_unscaled(9, false), 'result[2] = 9'); + assert((*result.data[3]) == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_2_keepdims_true() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(2, true); + assert((*result.data[0]) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5, false), 'result[1] = 5'); + assert((*result.data[2]) == FixedTrait::new_unscaled(9, false), 'result[2] = 9'); + assert((*result.data[3]) == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert((*result.shape[2]) == 1, 'result.shape[2] = 1'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(3, false); + } +} + diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo b/src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo new file mode 100644 index 000000000..919996c49 --- /dev/null +++ b/src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo @@ -0,0 +1,242 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Into, FP8x23Impl, FP8x23PartialEq + }; + use orion::numbers::fixed_point::core::FixedTrait; + + #[test] + #[available_gas(20000000)] + fn reduce_sum() { + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(3, false), 'result[0] = 3'); + assert(result.data.len() == 1, 'result.data.len = 1'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.reduce_sum(1, false); + } +} +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Into, FP8x23Impl, FP8x23PartialEq + }; + use orion::numbers::fixed_point::core::FixedTrait; + + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_false() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(2, false), 'result.data[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4, false), 'result.data[1] = 4'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 1, 'result.shape.len = 1'); + } + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_true() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(0, true); + + assert((*result.data[0]) == FixedTrait::new_unscaled(2, false), 'result.data[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4, false), 'result.data[1] = 4'); + assert((*result.shape[0]) == 1, 'result.shape[0] = 1'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_false() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(1, false); + + assert((*result.data[0]) == FixedTrait::new_unscaled(1, false), 'result.data[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5, false), 'result.data[1] = 5'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 1, 'result.shape.len = 1'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_true() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(1, true); + + assert((*result.data[0]) == FixedTrait::new_unscaled(1, false), 'result.data[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5, false), 'result.data[1] = 5'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 1, 'result.shape[1] = 1'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.reduce_sum(2, false); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Into, FP8x23Impl, FP8x23PartialEq + }; + use orion::numbers::fixed_point::core::FixedTrait; + + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_false() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(4, false), 'result[0] = 4'); + assert((*result.data[1]) == FixedTrait::new_unscaled(6, false), 'result[1] = 6'); + assert((*result.data[2]) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert((*result.data[3]) == FixedTrait::new_unscaled(10, false), 'result[3] = 10'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_true() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(0, true); + assert((*result.data[0]) == FixedTrait::new_unscaled(4, false), 'result[0] = 4'); + assert((*result.data[1]) == FixedTrait::new_unscaled(6, false), 'result[1] = 6'); + assert((*result.data[2]) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert((*result.data[3]) == FixedTrait::new_unscaled(10, false), 'result[3] = 10'); + assert((*result.shape[0]) == 1, 'result.shape[0] = 1'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert((*result.shape[2]) == 2, 'result.shape[2] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_false() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(1, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert((*result.data[2]) == FixedTrait::new_unscaled(10, false), 'result[2] = 10'); + assert((*result.data[3]) == FixedTrait::new_unscaled(12, false), 'result[3] = 12'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_true() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(1, true); + assert((*result.data[0]) == FixedTrait::new_unscaled(2, false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert((*result.data[2]) == FixedTrait::new_unscaled(10, false), 'result[2] = 10'); + assert((*result.data[3]) == FixedTrait::new_unscaled(12, false), 'result[3] = 12'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 1, 'result.shape[1] = 1'); + assert((*result.shape[2]) == 2, 'result.shape[2] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_2_keepdims_false() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(2, false); + assert((*result.data[0]) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5, false), 'result[1] = 5'); + assert((*result.data[2]) == FixedTrait::new_unscaled(9, false), 'result[2] = 9'); + assert((*result.data[3]) == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_2_keepdims_true() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(2, true); + assert((*result.data[0]) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5, false), 'result[1] = 5'); + assert((*result.data[2]) == FixedTrait::new_unscaled(9, false), 'result[2] = 9'); + assert((*result.data[3]) == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); + assert((*result.shape[0]) == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]) == 2, 'result.shape[1] = 2'); + assert((*result.shape[2]) == 1, 'result.shape[2] = 1'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = fp_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(3, false); + } +} + diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_i32_test.cairo b/src/tests/operators/math/reduce_sum/reduce_sum_i32_test.cairo new file mode 100644 index 000000000..d0ce6da8f --- /dev/null +++ b/src/tests/operators/math/reduce_sum/reduce_sum_i32_test.cairo @@ -0,0 +1,228 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn reduce_sum() { + let tensor = i32_tensor_1x3_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]).into() == 3, 'result[0] = 3'); + assert(result.data.len() == 1, 'result.data.len = 1'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = i32_tensor_1x3_helper(); + + let result = tensor.reduce_sum(1, false); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_false() { + let tensor = i32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]).into() == 2, 'result.data[0] = 2'); + assert((*result.data[1]).into() == 4, 'result.data[1] = 4'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 1, 'result.shape.len = 1'); + } + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_true() { + let tensor = i32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(0, true); + + assert((*result.data[0]).into() == 2, 'result.data[0] = 2'); + assert((*result.data[1]).into() == 4, 'result.data[1] = 4'); + assert((*result.shape[0]).into() == 1, 'result.shape[0] = 1'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_false() { + let tensor = i32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(1, false); + + assert((*result.data[0]).into() == 1, 'result.data[0] = 1'); + assert((*result.data[1]).into() == 5, 'result.data[1] = 5'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 1, 'result.shape.len = 1'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_true() { + let tensor = i32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(1, true); + + assert((*result.data[0]).into() == 1, 'result.data[0] = 1'); + assert((*result.data[1]).into() == 5, 'result.data[1] = 5'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 1, 'result.shape[1] = 1'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = i32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(2, false); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_false() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 6, 'result[1] = 6'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 10, 'result[3] = 10'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_true() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(0, true); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 6, 'result[1] = 6'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 10, 'result[3] = 10'); + assert((*result.shape[0]).into() == 1, 'result.shape[0] = 1'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert((*result.shape[2]).into() == 2, 'result.shape[2] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_false() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(1, false); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 10, 'result[2] = 10'); + assert((*result.data[3]).into() == 12, 'result[3] = 12'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_true() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(1, true); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 10, 'result[2] = 10'); + assert((*result.data[3]).into() == 12, 'result[3] = 12'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 1, 'result.shape[1] = 1'); + assert((*result.shape[2]).into() == 2, 'result.shape[2] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_2_keepdims_false() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(2, false); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 5, 'result[1] = 5'); + assert((*result.data[2]).into() == 9, 'result[2] = 9'); + assert((*result.data[3]).into() == 13, 'result[3] = 13'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_2_keepdims_true() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(2, true); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 5, 'result[1] = 5'); + assert((*result.data[2]).into() == 9, 'result[2] = 9'); + assert((*result.data[3]).into() == 13, 'result[3] = 13'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert((*result.shape[2]).into() == 1, 'result.shape[2] = 1'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = i32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(3, false); + } +} diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_u32_test.cairo b/src/tests/operators/math/reduce_sum/reduce_sum_u32_test.cairo new file mode 100644 index 000000000..246ed569c --- /dev/null +++ b/src/tests/operators/math/reduce_sum/reduce_sum_u32_test.cairo @@ -0,0 +1,228 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn reduce_sum() { + let tensor = u32_tensor_1x3_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]).into() == 3, 'result[0] = 3'); + assert(result.data.len() == 1, 'result.data.len = 1'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = u32_tensor_1x3_helper(); + + let result = tensor.reduce_sum(1, false); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_false() { + let tensor = u32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]).into() == 2, 'result.data[0] = 2'); + assert((*result.data[1]).into() == 4, 'result.data[1] = 4'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 1, 'result.shape.len = 1'); + } + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_true() { + let tensor = u32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(0, true); + + assert((*result.data[0]).into() == 2, 'result.data[0] = 2'); + assert((*result.data[1]).into() == 4, 'result.data[1] = 4'); + assert((*result.shape[0]).into() == 1, 'result.shape[0] = 1'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_false() { + let tensor = u32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(1, false); + + assert((*result.data[0]).into() == 1, 'result.data[0] = 1'); + assert((*result.data[1]).into() == 5, 'result.data[1] = 5'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 1, 'result.shape.len = 1'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_true() { + let tensor = u32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(1, true); + + assert((*result.data[0]).into() == 1, 'result.data[0] = 1'); + assert((*result.data[1]).into() == 5, 'result.data[1] = 5'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 1, 'result.shape[1] = 1'); + assert(result.data.len() == 2, 'result.data.len = 1'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = u32_tensor_2x2_helper(); + + let result = tensor.reduce_sum(2, false); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::TensorTrait; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_false() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(0, false); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 6, 'result[1] = 6'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 10, 'result[3] = 10'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_0_keepdims_true() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(0, true); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 6, 'result[1] = 6'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 10, 'result[3] = 10'); + assert((*result.shape[0]).into() == 1, 'result.shape[0] = 1'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert((*result.shape[2]).into() == 2, 'result.shape[2] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_false() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(1, false); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 10, 'result[2] = 10'); + assert((*result.data[3]).into() == 12, 'result[3] = 12'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_1_keepdims_true() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(1, true); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 10, 'result[2] = 10'); + assert((*result.data[3]).into() == 12, 'result[3] = 12'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 1, 'result.shape[1] = 1'); + assert((*result.shape[2]).into() == 2, 'result.shape[2] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_2_keepdims_false() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(2, false); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 5, 'result[1] = 5'); + assert((*result.data[2]).into() == 9, 'result[2] = 9'); + assert((*result.data[3]).into() == 13, 'result[3] = 13'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 2, 'result.shape.len = 2'); + } + + #[test] + #[available_gas(20000000)] + fn axis_2_keepdims_true() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(2, true); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 5, 'result[1] = 5'); + assert((*result.data[2]).into() == 9, 'result[2] = 9'); + assert((*result.data[3]).into() == 13, 'result[3] = 13'); + assert((*result.shape[0]).into() == 2, 'result.shape[0] = 2'); + assert((*result.shape[1]).into() == 2, 'result.shape[1] = 2'); + assert((*result.shape[2]).into() == 1, 'result.shape[2] = 1'); + assert(result.data.len() == 4, 'result.data.len = 4'); + assert(result.shape.len() == 3, 'result.shape.len = 2'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn out_of_dim() { + let tensor = u32_tensor_2x2x2_helper(); + + let result = tensor.reduce_sum(3, false); + } +} diff --git a/src/tests/operators/math/reduce_sum_test.cairo b/src/tests/operators/math/reduce_sum_test.cairo deleted file mode 100644 index d9ef43888..000000000 --- a/src/tests/operators/math/reduce_sum_test.cairo +++ /dev/null @@ -1,45 +0,0 @@ -use array::SpanTrait; -use traits::Into; - -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::operators::tensor::core::TensorTrait; -use orion::tests::helpers::tensor::i32::{i32_tensor_2x2x2_helper, i32_tensor_1x3_helper}; - -use debug::PrintTrait; - -#[test] -#[available_gas(20000000)] -fn reduce_sum_1d() { - let tensor = i32_tensor_1x3_helper(); - - let result = tensor.reduce_sum(0, false); - assert((*result.data[0]).into() == 3, 'result[0] = 3'); - assert(result.data.len() == 1, 'result.len = 1'); -} - -#[test] -#[available_gas(20000000)] -fn reduce_sum_3d() { - let tensor = i32_tensor_2x2x2_helper(); - - let result = tensor.reduce_sum(0, false); - - assert((*result.data[0]).into() == 4, 'result[0] = 4'); - assert((*result.data[1]).into() == 6, 'result[1] = 6'); - assert((*result.data[2]).into() == 8, 'result[2] = 8'); - assert((*result.data[3]).into() == 10, 'result[3] = 10'); - - let result = tensor.reduce_sum(1, false).data; - - assert((*result[0]).into() == 2, 'result[0] = 2'); - assert((*result[1]).into() == 4, 'result[1] = 4'); - assert((*result[2]).into() == 10, 'result[2] = 10'); - assert((*result[3]).into() == 12, 'result[3] = 12'); - - let result = tensor.reduce_sum(2, false).data; - - assert((*result[0]).into() == 1, 'result[0] = 1'); - assert((*result[1]).into() == 5, 'result[1] = 5'); - assert((*result[2]).into() == 9, 'result[2] = 9'); - assert((*result[3]).into() == 13, 'result[3] = 13'); -} From 6f2813c47a21a606d1212d03d839bfca879d88c0 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 14:58:20 +0300 Subject: [PATCH 033/126] reorganize tensor tests --- src/tests/operators.cairo | 2 -- src/tests/operators/tensor.cairo | 4 +++- src/tests/operators/{ => tensor}/linalg.cairo | 0 src/tests/operators/{ => tensor}/linalg/matmul.cairo | 0 .../operators/{ => tensor}/linalg/matmul/matmul_fp_test.cairo | 0 .../linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo | 0 .../linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo | 0 .../{ => tensor}/linalg/matmul/matmul_i32_test.cairo | 0 .../{ => tensor}/linalg/matmul/matmul_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math.cairo | 0 src/tests/operators/{ => tensor}/math/abs.cairo | 0 src/tests/operators/{ => tensor}/math/abs/abs_fp_test.cairo | 0 .../{ => tensor}/math/abs/abs_fp_test/abs_fp16x16_test.cairo | 0 .../{ => tensor}/math/abs/abs_fp_test/abs_fp8x23_test.cairo | 0 src/tests/operators/{ => tensor}/math/abs/abs_i32_test.cairo | 0 src/tests/operators/{ => tensor}/math/abs/abs_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/argmax.cairo | 0 .../operators/{ => tensor}/math/argmax/argmax_fp_test.cairo | 0 .../math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo | 0 .../math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo | 0 .../operators/{ => tensor}/math/argmax/argmax_i32_test.cairo | 0 .../operators/{ => tensor}/math/argmax/argmax_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/argmin.cairo | 0 .../operators/{ => tensor}/math/argmin/argmin_fp_test.cairo | 0 .../math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo | 0 .../math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo | 0 .../operators/{ => tensor}/math/argmin/argmin_i32_test.cairo | 0 .../operators/{ => tensor}/math/argmin/argmin_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/ceil.cairo | 0 src/tests/operators/{ => tensor}/math/ceil/ceil_fp_test.cairo | 0 .../math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo | 0 .../math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo | 0 .../operators/{ => tensor}/math/ceil/ceil_i32_test.cairo | 0 .../operators/{ => tensor}/math/ceil/ceil_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/equal.cairo | 0 .../operators/{ => tensor}/math/equal/equal_fp_test.cairo | 0 .../math/equal/equal_fp_test/equal_fp16x16_test.cairo | 0 .../math/equal/equal_fp_test/equal_fp8x23_test.cairo | 0 .../operators/{ => tensor}/math/equal/equal_i32_test.cairo | 0 .../operators/{ => tensor}/math/equal/equal_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/exp.cairo | 0 src/tests/operators/{ => tensor}/math/exp/exp_fp_test.cairo | 0 .../{ => tensor}/math/exp/exp_fp_test/exp_fp16x16_test.cairo | 0 .../{ => tensor}/math/exp/exp_fp_test/exp_fp8x23_test.cairo | 0 src/tests/operators/{ => tensor}/math/exp/exp_i32_test.cairo | 0 src/tests/operators/{ => tensor}/math/exp/exp_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/greater.cairo | 0 .../operators/{ => tensor}/math/greater/greater_fp_test.cairo | 0 .../math/greater/greater_fp_test/greater_fp16x16_test.cairo | 0 .../math/greater/greater_fp_test/greater_fp8x23_test.cairo | 0 .../{ => tensor}/math/greater/greater_i32_test.cairo | 0 .../{ => tensor}/math/greater/greater_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/greater_equal.cairo | 0 .../math/greater_equal/greater_equal_fp_test.cairo | 0 .../greater_equal_fp_test/greater_equal_fp16x16_test.cairo | 0 .../greater_equal_fp_test/greater_equal_fp8x23_test.cairo | 0 .../math/greater_equal/greater_equal_i32_test.cairo | 0 .../math/greater_equal/greater_equal_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/less.cairo | 0 src/tests/operators/{ => tensor}/math/less/less_fp_test.cairo | 0 .../math/less/less_fp_test/less_fp16x16_test.cairo | 0 .../math/less/less_fp_test/less_fp8x23_test.cairo | 0 .../operators/{ => tensor}/math/less/less_i32_test.cairo | 0 .../operators/{ => tensor}/math/less/less_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/less_equal.cairo | 0 .../{ => tensor}/math/less_equal/less_equal_fp_test.cairo | 0 .../less_equal_fp_test/less_equal_fp16x16_test.cairo | 0 .../less_equal_fp_test/less_equal_fp8x23_test.cairo | 0 .../{ => tensor}/math/less_equal/less_equal_i32_test.cairo | 0 .../{ => tensor}/math/less_equal/less_equal_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/ln.cairo | 0 src/tests/operators/{ => tensor}/math/ln/ln_fp_test.cairo | 0 .../{ => tensor}/math/ln/ln_fp_test/ln_fp16x16_test.cairo | 0 .../{ => tensor}/math/ln/ln_fp_test/ln_fp8x23_test.cairo | 0 src/tests/operators/{ => tensor}/math/ln/ln_i32_test.cairo | 0 src/tests/operators/{ => tensor}/math/ln/ln_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/max.cairo | 0 src/tests/operators/{ => tensor}/math/max/max_fp_test.cairo | 0 .../{ => tensor}/math/max/max_fp_test/max_fp16x16_test.cairo | 0 .../{ => tensor}/math/max/max_fp_test/max_fp8x23_test.cairo | 0 src/tests/operators/{ => tensor}/math/max/max_i32_test.cairo | 0 src/tests/operators/{ => tensor}/math/max/max_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/min.cairo | 0 src/tests/operators/{ => tensor}/math/min/min_fp_test.cairo | 0 .../{ => tensor}/math/min/min_fp_test/min_fp16x16_test.cairo | 0 .../{ => tensor}/math/min/min_fp_test/min_fp8x23_test.cairo | 0 src/tests/operators/{ => tensor}/math/min/min_i32_test.cairo | 0 src/tests/operators/{ => tensor}/math/min/min_u32_test.cairo | 0 src/tests/operators/{ => tensor}/math/reduce_sum.cairo | 0 .../{ => tensor}/math/reduce_sum/reduce_sum_fp_test.cairo | 0 .../reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo | 0 .../reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo | 0 .../{ => tensor}/math/reduce_sum/reduce_sum_i32_test.cairo | 0 .../{ => tensor}/math/reduce_sum/reduce_sum_u32_test.cairo | 0 94 files changed, 3 insertions(+), 3 deletions(-) rename src/tests/operators/{ => tensor}/linalg.cairo (100%) rename src/tests/operators/{ => tensor}/linalg/matmul.cairo (100%) rename src/tests/operators/{ => tensor}/linalg/matmul/matmul_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/linalg/matmul/matmul_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/linalg/matmul/matmul_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math.cairo (100%) rename src/tests/operators/{ => tensor}/math/abs.cairo (100%) rename src/tests/operators/{ => tensor}/math/abs/abs_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/abs/abs_fp_test/abs_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/abs/abs_fp_test/abs_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/abs/abs_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/abs/abs_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmax.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmax/argmax_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmax/argmax_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmax/argmax_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmin.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmin/argmin_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmin/argmin_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/argmin/argmin_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ceil.cairo (100%) rename src/tests/operators/{ => tensor}/math/ceil/ceil_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ceil/ceil_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ceil/ceil_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/equal.cairo (100%) rename src/tests/operators/{ => tensor}/math/equal/equal_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/equal/equal_fp_test/equal_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/equal/equal_fp_test/equal_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/equal/equal_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/equal/equal_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/exp.cairo (100%) rename src/tests/operators/{ => tensor}/math/exp/exp_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/exp/exp_fp_test/exp_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/exp/exp_fp_test/exp_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/exp/exp_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/exp/exp_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater/greater_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater/greater_fp_test/greater_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater/greater_fp_test/greater_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater/greater_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater/greater_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater_equal.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater_equal/greater_equal_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater_equal/greater_equal_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/greater_equal/greater_equal_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less.cairo (100%) rename src/tests/operators/{ => tensor}/math/less/less_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less/less_fp_test/less_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less/less_fp_test/less_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less/less_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less/less_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less_equal.cairo (100%) rename src/tests/operators/{ => tensor}/math/less_equal/less_equal_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less_equal/less_equal_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/less_equal/less_equal_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ln.cairo (100%) rename src/tests/operators/{ => tensor}/math/ln/ln_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ln/ln_fp_test/ln_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ln/ln_fp_test/ln_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ln/ln_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/ln/ln_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/max.cairo (100%) rename src/tests/operators/{ => tensor}/math/max/max_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/max/max_fp_test/max_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/max/max_fp_test/max_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/max/max_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/max/max_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/min.cairo (100%) rename src/tests/operators/{ => tensor}/math/min/min_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/min/min_fp_test/min_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/min/min_fp_test/min_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/min/min_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/min/min_u32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/reduce_sum.cairo (100%) rename src/tests/operators/{ => tensor}/math/reduce_sum/reduce_sum_fp_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/reduce_sum/reduce_sum_i32_test.cairo (100%) rename src/tests/operators/{ => tensor}/math/reduce_sum/reduce_sum_u32_test.cairo (100%) diff --git a/src/tests/operators.cairo b/src/tests/operators.cairo index 2dbe7792b..391e7133c 100644 --- a/src/tests/operators.cairo +++ b/src/tests/operators.cairo @@ -1,4 +1,2 @@ -mod linalg; -mod math; mod nn; mod tensor; diff --git a/src/tests/operators/tensor.cairo b/src/tests/operators/tensor.cairo index 0143edfc3..df3dfc814 100644 --- a/src/tests/operators/tensor.cairo +++ b/src/tests/operators/tensor.cairo @@ -1 +1,3 @@ -mod tensor_test; \ No newline at end of file +mod tensor_test; +mod math; +mod linalg; \ No newline at end of file diff --git a/src/tests/operators/linalg.cairo b/src/tests/operators/tensor/linalg.cairo similarity index 100% rename from src/tests/operators/linalg.cairo rename to src/tests/operators/tensor/linalg.cairo diff --git a/src/tests/operators/linalg/matmul.cairo b/src/tests/operators/tensor/linalg/matmul.cairo similarity index 100% rename from src/tests/operators/linalg/matmul.cairo rename to src/tests/operators/tensor/linalg/matmul.cairo diff --git a/src/tests/operators/linalg/matmul/matmul_fp_test.cairo b/src/tests/operators/tensor/linalg/matmul/matmul_fp_test.cairo similarity index 100% rename from src/tests/operators/linalg/matmul/matmul_fp_test.cairo rename to src/tests/operators/tensor/linalg/matmul/matmul_fp_test.cairo diff --git a/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo b/src/tests/operators/tensor/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo rename to src/tests/operators/tensor/linalg/matmul/matmul_fp_test/matmul_fp16x16_test.cairo diff --git a/src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo b/src/tests/operators/tensor/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo rename to src/tests/operators/tensor/linalg/matmul/matmul_fp_test/matmul_fp8x23_test.cairo diff --git a/src/tests/operators/linalg/matmul/matmul_i32_test.cairo b/src/tests/operators/tensor/linalg/matmul/matmul_i32_test.cairo similarity index 100% rename from src/tests/operators/linalg/matmul/matmul_i32_test.cairo rename to src/tests/operators/tensor/linalg/matmul/matmul_i32_test.cairo diff --git a/src/tests/operators/linalg/matmul/matmul_u32_test.cairo b/src/tests/operators/tensor/linalg/matmul/matmul_u32_test.cairo similarity index 100% rename from src/tests/operators/linalg/matmul/matmul_u32_test.cairo rename to src/tests/operators/tensor/linalg/matmul/matmul_u32_test.cairo diff --git a/src/tests/operators/math.cairo b/src/tests/operators/tensor/math.cairo similarity index 100% rename from src/tests/operators/math.cairo rename to src/tests/operators/tensor/math.cairo diff --git a/src/tests/operators/math/abs.cairo b/src/tests/operators/tensor/math/abs.cairo similarity index 100% rename from src/tests/operators/math/abs.cairo rename to src/tests/operators/tensor/math/abs.cairo diff --git a/src/tests/operators/math/abs/abs_fp_test.cairo b/src/tests/operators/tensor/math/abs/abs_fp_test.cairo similarity index 100% rename from src/tests/operators/math/abs/abs_fp_test.cairo rename to src/tests/operators/tensor/math/abs/abs_fp_test.cairo diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo b/src/tests/operators/tensor/math/abs/abs_fp_test/abs_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/abs/abs_fp_test/abs_fp16x16_test.cairo rename to src/tests/operators/tensor/math/abs/abs_fp_test/abs_fp16x16_test.cairo diff --git a/src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo b/src/tests/operators/tensor/math/abs/abs_fp_test/abs_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/abs/abs_fp_test/abs_fp8x23_test.cairo rename to src/tests/operators/tensor/math/abs/abs_fp_test/abs_fp8x23_test.cairo diff --git a/src/tests/operators/math/abs/abs_i32_test.cairo b/src/tests/operators/tensor/math/abs/abs_i32_test.cairo similarity index 100% rename from src/tests/operators/math/abs/abs_i32_test.cairo rename to src/tests/operators/tensor/math/abs/abs_i32_test.cairo diff --git a/src/tests/operators/math/abs/abs_u32_test.cairo b/src/tests/operators/tensor/math/abs/abs_u32_test.cairo similarity index 100% rename from src/tests/operators/math/abs/abs_u32_test.cairo rename to src/tests/operators/tensor/math/abs/abs_u32_test.cairo diff --git a/src/tests/operators/math/argmax.cairo b/src/tests/operators/tensor/math/argmax.cairo similarity index 100% rename from src/tests/operators/math/argmax.cairo rename to src/tests/operators/tensor/math/argmax.cairo diff --git a/src/tests/operators/math/argmax/argmax_fp_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_fp_test.cairo similarity index 100% rename from src/tests/operators/math/argmax/argmax_fp_test.cairo rename to src/tests/operators/tensor/math/argmax/argmax_fp_test.cairo diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo rename to src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo diff --git a/src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo rename to src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo diff --git a/src/tests/operators/math/argmax/argmax_i32_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_i32_test.cairo similarity index 100% rename from src/tests/operators/math/argmax/argmax_i32_test.cairo rename to src/tests/operators/tensor/math/argmax/argmax_i32_test.cairo diff --git a/src/tests/operators/math/argmax/argmax_u32_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_u32_test.cairo similarity index 100% rename from src/tests/operators/math/argmax/argmax_u32_test.cairo rename to src/tests/operators/tensor/math/argmax/argmax_u32_test.cairo diff --git a/src/tests/operators/math/argmin.cairo b/src/tests/operators/tensor/math/argmin.cairo similarity index 100% rename from src/tests/operators/math/argmin.cairo rename to src/tests/operators/tensor/math/argmin.cairo diff --git a/src/tests/operators/math/argmin/argmin_fp_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_fp_test.cairo similarity index 100% rename from src/tests/operators/math/argmin/argmin_fp_test.cairo rename to src/tests/operators/tensor/math/argmin/argmin_fp_test.cairo diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo rename to src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo diff --git a/src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo rename to src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo diff --git a/src/tests/operators/math/argmin/argmin_i32_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_i32_test.cairo similarity index 100% rename from src/tests/operators/math/argmin/argmin_i32_test.cairo rename to src/tests/operators/tensor/math/argmin/argmin_i32_test.cairo diff --git a/src/tests/operators/math/argmin/argmin_u32_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_u32_test.cairo similarity index 100% rename from src/tests/operators/math/argmin/argmin_u32_test.cairo rename to src/tests/operators/tensor/math/argmin/argmin_u32_test.cairo diff --git a/src/tests/operators/math/ceil.cairo b/src/tests/operators/tensor/math/ceil.cairo similarity index 100% rename from src/tests/operators/math/ceil.cairo rename to src/tests/operators/tensor/math/ceil.cairo diff --git a/src/tests/operators/math/ceil/ceil_fp_test.cairo b/src/tests/operators/tensor/math/ceil/ceil_fp_test.cairo similarity index 100% rename from src/tests/operators/math/ceil/ceil_fp_test.cairo rename to src/tests/operators/tensor/math/ceil/ceil_fp_test.cairo diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo b/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo rename to src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo diff --git a/src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo b/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo rename to src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo diff --git a/src/tests/operators/math/ceil/ceil_i32_test.cairo b/src/tests/operators/tensor/math/ceil/ceil_i32_test.cairo similarity index 100% rename from src/tests/operators/math/ceil/ceil_i32_test.cairo rename to src/tests/operators/tensor/math/ceil/ceil_i32_test.cairo diff --git a/src/tests/operators/math/ceil/ceil_u32_test.cairo b/src/tests/operators/tensor/math/ceil/ceil_u32_test.cairo similarity index 100% rename from src/tests/operators/math/ceil/ceil_u32_test.cairo rename to src/tests/operators/tensor/math/ceil/ceil_u32_test.cairo diff --git a/src/tests/operators/math/equal.cairo b/src/tests/operators/tensor/math/equal.cairo similarity index 100% rename from src/tests/operators/math/equal.cairo rename to src/tests/operators/tensor/math/equal.cairo diff --git a/src/tests/operators/math/equal/equal_fp_test.cairo b/src/tests/operators/tensor/math/equal/equal_fp_test.cairo similarity index 100% rename from src/tests/operators/math/equal/equal_fp_test.cairo rename to src/tests/operators/tensor/math/equal/equal_fp_test.cairo diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo b/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/equal/equal_fp_test/equal_fp16x16_test.cairo rename to src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp16x16_test.cairo diff --git a/src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo b/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/equal/equal_fp_test/equal_fp8x23_test.cairo rename to src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp8x23_test.cairo diff --git a/src/tests/operators/math/equal/equal_i32_test.cairo b/src/tests/operators/tensor/math/equal/equal_i32_test.cairo similarity index 100% rename from src/tests/operators/math/equal/equal_i32_test.cairo rename to src/tests/operators/tensor/math/equal/equal_i32_test.cairo diff --git a/src/tests/operators/math/equal/equal_u32_test.cairo b/src/tests/operators/tensor/math/equal/equal_u32_test.cairo similarity index 100% rename from src/tests/operators/math/equal/equal_u32_test.cairo rename to src/tests/operators/tensor/math/equal/equal_u32_test.cairo diff --git a/src/tests/operators/math/exp.cairo b/src/tests/operators/tensor/math/exp.cairo similarity index 100% rename from src/tests/operators/math/exp.cairo rename to src/tests/operators/tensor/math/exp.cairo diff --git a/src/tests/operators/math/exp/exp_fp_test.cairo b/src/tests/operators/tensor/math/exp/exp_fp_test.cairo similarity index 100% rename from src/tests/operators/math/exp/exp_fp_test.cairo rename to src/tests/operators/tensor/math/exp/exp_fp_test.cairo diff --git a/src/tests/operators/math/exp/exp_fp_test/exp_fp16x16_test.cairo b/src/tests/operators/tensor/math/exp/exp_fp_test/exp_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/exp/exp_fp_test/exp_fp16x16_test.cairo rename to src/tests/operators/tensor/math/exp/exp_fp_test/exp_fp16x16_test.cairo diff --git a/src/tests/operators/math/exp/exp_fp_test/exp_fp8x23_test.cairo b/src/tests/operators/tensor/math/exp/exp_fp_test/exp_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/exp/exp_fp_test/exp_fp8x23_test.cairo rename to src/tests/operators/tensor/math/exp/exp_fp_test/exp_fp8x23_test.cairo diff --git a/src/tests/operators/math/exp/exp_i32_test.cairo b/src/tests/operators/tensor/math/exp/exp_i32_test.cairo similarity index 100% rename from src/tests/operators/math/exp/exp_i32_test.cairo rename to src/tests/operators/tensor/math/exp/exp_i32_test.cairo diff --git a/src/tests/operators/math/exp/exp_u32_test.cairo b/src/tests/operators/tensor/math/exp/exp_u32_test.cairo similarity index 100% rename from src/tests/operators/math/exp/exp_u32_test.cairo rename to src/tests/operators/tensor/math/exp/exp_u32_test.cairo diff --git a/src/tests/operators/math/greater.cairo b/src/tests/operators/tensor/math/greater.cairo similarity index 100% rename from src/tests/operators/math/greater.cairo rename to src/tests/operators/tensor/math/greater.cairo diff --git a/src/tests/operators/math/greater/greater_fp_test.cairo b/src/tests/operators/tensor/math/greater/greater_fp_test.cairo similarity index 100% rename from src/tests/operators/math/greater/greater_fp_test.cairo rename to src/tests/operators/tensor/math/greater/greater_fp_test.cairo diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo b/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/greater/greater_fp_test/greater_fp16x16_test.cairo rename to src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp16x16_test.cairo diff --git a/src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo b/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/greater/greater_fp_test/greater_fp8x23_test.cairo rename to src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp8x23_test.cairo diff --git a/src/tests/operators/math/greater/greater_i32_test.cairo b/src/tests/operators/tensor/math/greater/greater_i32_test.cairo similarity index 100% rename from src/tests/operators/math/greater/greater_i32_test.cairo rename to src/tests/operators/tensor/math/greater/greater_i32_test.cairo diff --git a/src/tests/operators/math/greater/greater_u32_test.cairo b/src/tests/operators/tensor/math/greater/greater_u32_test.cairo similarity index 100% rename from src/tests/operators/math/greater/greater_u32_test.cairo rename to src/tests/operators/tensor/math/greater/greater_u32_test.cairo diff --git a/src/tests/operators/math/greater_equal.cairo b/src/tests/operators/tensor/math/greater_equal.cairo similarity index 100% rename from src/tests/operators/math/greater_equal.cairo rename to src/tests/operators/tensor/math/greater_equal.cairo diff --git a/src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test.cairo similarity index 100% rename from src/tests/operators/math/greater_equal/greater_equal_fp_test.cairo rename to src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test.cairo diff --git a/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo rename to src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo diff --git a/src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo rename to src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo diff --git a/src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_i32_test.cairo similarity index 100% rename from src/tests/operators/math/greater_equal/greater_equal_i32_test.cairo rename to src/tests/operators/tensor/math/greater_equal/greater_equal_i32_test.cairo diff --git a/src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_u32_test.cairo similarity index 100% rename from src/tests/operators/math/greater_equal/greater_equal_u32_test.cairo rename to src/tests/operators/tensor/math/greater_equal/greater_equal_u32_test.cairo diff --git a/src/tests/operators/math/less.cairo b/src/tests/operators/tensor/math/less.cairo similarity index 100% rename from src/tests/operators/math/less.cairo rename to src/tests/operators/tensor/math/less.cairo diff --git a/src/tests/operators/math/less/less_fp_test.cairo b/src/tests/operators/tensor/math/less/less_fp_test.cairo similarity index 100% rename from src/tests/operators/math/less/less_fp_test.cairo rename to src/tests/operators/tensor/math/less/less_fp_test.cairo diff --git a/src/tests/operators/math/less/less_fp_test/less_fp16x16_test.cairo b/src/tests/operators/tensor/math/less/less_fp_test/less_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/less/less_fp_test/less_fp16x16_test.cairo rename to src/tests/operators/tensor/math/less/less_fp_test/less_fp16x16_test.cairo diff --git a/src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo b/src/tests/operators/tensor/math/less/less_fp_test/less_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/less/less_fp_test/less_fp8x23_test.cairo rename to src/tests/operators/tensor/math/less/less_fp_test/less_fp8x23_test.cairo diff --git a/src/tests/operators/math/less/less_i32_test.cairo b/src/tests/operators/tensor/math/less/less_i32_test.cairo similarity index 100% rename from src/tests/operators/math/less/less_i32_test.cairo rename to src/tests/operators/tensor/math/less/less_i32_test.cairo diff --git a/src/tests/operators/math/less/less_u32_test.cairo b/src/tests/operators/tensor/math/less/less_u32_test.cairo similarity index 100% rename from src/tests/operators/math/less/less_u32_test.cairo rename to src/tests/operators/tensor/math/less/less_u32_test.cairo diff --git a/src/tests/operators/math/less_equal.cairo b/src/tests/operators/tensor/math/less_equal.cairo similarity index 100% rename from src/tests/operators/math/less_equal.cairo rename to src/tests/operators/tensor/math/less_equal.cairo diff --git a/src/tests/operators/math/less_equal/less_equal_fp_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_fp_test.cairo similarity index 100% rename from src/tests/operators/math/less_equal/less_equal_fp_test.cairo rename to src/tests/operators/tensor/math/less_equal/less_equal_fp_test.cairo diff --git a/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo rename to src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo diff --git a/src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo rename to src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo diff --git a/src/tests/operators/math/less_equal/less_equal_i32_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_i32_test.cairo similarity index 100% rename from src/tests/operators/math/less_equal/less_equal_i32_test.cairo rename to src/tests/operators/tensor/math/less_equal/less_equal_i32_test.cairo diff --git a/src/tests/operators/math/less_equal/less_equal_u32_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_u32_test.cairo similarity index 100% rename from src/tests/operators/math/less_equal/less_equal_u32_test.cairo rename to src/tests/operators/tensor/math/less_equal/less_equal_u32_test.cairo diff --git a/src/tests/operators/math/ln.cairo b/src/tests/operators/tensor/math/ln.cairo similarity index 100% rename from src/tests/operators/math/ln.cairo rename to src/tests/operators/tensor/math/ln.cairo diff --git a/src/tests/operators/math/ln/ln_fp_test.cairo b/src/tests/operators/tensor/math/ln/ln_fp_test.cairo similarity index 100% rename from src/tests/operators/math/ln/ln_fp_test.cairo rename to src/tests/operators/tensor/math/ln/ln_fp_test.cairo diff --git a/src/tests/operators/math/ln/ln_fp_test/ln_fp16x16_test.cairo b/src/tests/operators/tensor/math/ln/ln_fp_test/ln_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/ln/ln_fp_test/ln_fp16x16_test.cairo rename to src/tests/operators/tensor/math/ln/ln_fp_test/ln_fp16x16_test.cairo diff --git a/src/tests/operators/math/ln/ln_fp_test/ln_fp8x23_test.cairo b/src/tests/operators/tensor/math/ln/ln_fp_test/ln_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/ln/ln_fp_test/ln_fp8x23_test.cairo rename to src/tests/operators/tensor/math/ln/ln_fp_test/ln_fp8x23_test.cairo diff --git a/src/tests/operators/math/ln/ln_i32_test.cairo b/src/tests/operators/tensor/math/ln/ln_i32_test.cairo similarity index 100% rename from src/tests/operators/math/ln/ln_i32_test.cairo rename to src/tests/operators/tensor/math/ln/ln_i32_test.cairo diff --git a/src/tests/operators/math/ln/ln_u32_test.cairo b/src/tests/operators/tensor/math/ln/ln_u32_test.cairo similarity index 100% rename from src/tests/operators/math/ln/ln_u32_test.cairo rename to src/tests/operators/tensor/math/ln/ln_u32_test.cairo diff --git a/src/tests/operators/math/max.cairo b/src/tests/operators/tensor/math/max.cairo similarity index 100% rename from src/tests/operators/math/max.cairo rename to src/tests/operators/tensor/math/max.cairo diff --git a/src/tests/operators/math/max/max_fp_test.cairo b/src/tests/operators/tensor/math/max/max_fp_test.cairo similarity index 100% rename from src/tests/operators/math/max/max_fp_test.cairo rename to src/tests/operators/tensor/math/max/max_fp_test.cairo diff --git a/src/tests/operators/math/max/max_fp_test/max_fp16x16_test.cairo b/src/tests/operators/tensor/math/max/max_fp_test/max_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/max/max_fp_test/max_fp16x16_test.cairo rename to src/tests/operators/tensor/math/max/max_fp_test/max_fp16x16_test.cairo diff --git a/src/tests/operators/math/max/max_fp_test/max_fp8x23_test.cairo b/src/tests/operators/tensor/math/max/max_fp_test/max_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/max/max_fp_test/max_fp8x23_test.cairo rename to src/tests/operators/tensor/math/max/max_fp_test/max_fp8x23_test.cairo diff --git a/src/tests/operators/math/max/max_i32_test.cairo b/src/tests/operators/tensor/math/max/max_i32_test.cairo similarity index 100% rename from src/tests/operators/math/max/max_i32_test.cairo rename to src/tests/operators/tensor/math/max/max_i32_test.cairo diff --git a/src/tests/operators/math/max/max_u32_test.cairo b/src/tests/operators/tensor/math/max/max_u32_test.cairo similarity index 100% rename from src/tests/operators/math/max/max_u32_test.cairo rename to src/tests/operators/tensor/math/max/max_u32_test.cairo diff --git a/src/tests/operators/math/min.cairo b/src/tests/operators/tensor/math/min.cairo similarity index 100% rename from src/tests/operators/math/min.cairo rename to src/tests/operators/tensor/math/min.cairo diff --git a/src/tests/operators/math/min/min_fp_test.cairo b/src/tests/operators/tensor/math/min/min_fp_test.cairo similarity index 100% rename from src/tests/operators/math/min/min_fp_test.cairo rename to src/tests/operators/tensor/math/min/min_fp_test.cairo diff --git a/src/tests/operators/math/min/min_fp_test/min_fp16x16_test.cairo b/src/tests/operators/tensor/math/min/min_fp_test/min_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/min/min_fp_test/min_fp16x16_test.cairo rename to src/tests/operators/tensor/math/min/min_fp_test/min_fp16x16_test.cairo diff --git a/src/tests/operators/math/min/min_fp_test/min_fp8x23_test.cairo b/src/tests/operators/tensor/math/min/min_fp_test/min_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/min/min_fp_test/min_fp8x23_test.cairo rename to src/tests/operators/tensor/math/min/min_fp_test/min_fp8x23_test.cairo diff --git a/src/tests/operators/math/min/min_i32_test.cairo b/src/tests/operators/tensor/math/min/min_i32_test.cairo similarity index 100% rename from src/tests/operators/math/min/min_i32_test.cairo rename to src/tests/operators/tensor/math/min/min_i32_test.cairo diff --git a/src/tests/operators/math/min/min_u32_test.cairo b/src/tests/operators/tensor/math/min/min_u32_test.cairo similarity index 100% rename from src/tests/operators/math/min/min_u32_test.cairo rename to src/tests/operators/tensor/math/min/min_u32_test.cairo diff --git a/src/tests/operators/math/reduce_sum.cairo b/src/tests/operators/tensor/math/reduce_sum.cairo similarity index 100% rename from src/tests/operators/math/reduce_sum.cairo rename to src/tests/operators/tensor/math/reduce_sum.cairo diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_fp_test.cairo b/src/tests/operators/tensor/math/reduce_sum/reduce_sum_fp_test.cairo similarity index 100% rename from src/tests/operators/math/reduce_sum/reduce_sum_fp_test.cairo rename to src/tests/operators/tensor/math/reduce_sum/reduce_sum_fp_test.cairo diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo b/src/tests/operators/tensor/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo similarity index 100% rename from src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo rename to src/tests/operators/tensor/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp16x16_test.cairo diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo b/src/tests/operators/tensor/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo similarity index 100% rename from src/tests/operators/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo rename to src/tests/operators/tensor/math/reduce_sum/reduce_sum_fp_test/reduce_sum_fp8x23_test.cairo diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_i32_test.cairo b/src/tests/operators/tensor/math/reduce_sum/reduce_sum_i32_test.cairo similarity index 100% rename from src/tests/operators/math/reduce_sum/reduce_sum_i32_test.cairo rename to src/tests/operators/tensor/math/reduce_sum/reduce_sum_i32_test.cairo diff --git a/src/tests/operators/math/reduce_sum/reduce_sum_u32_test.cairo b/src/tests/operators/tensor/math/reduce_sum/reduce_sum_u32_test.cairo similarity index 100% rename from src/tests/operators/math/reduce_sum/reduce_sum_u32_test.cairo rename to src/tests/operators/tensor/math/reduce_sum/reduce_sum_u32_test.cairo From c0009e9588436d0e7fb68fdf258121dcc45b0e4f Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 15:19:32 +0300 Subject: [PATCH 034/126] refactor tensor at tests --- src/tests/operators/tensor.cairo | 3 +- src/tests/operators/tensor/core.cairo | 1 + src/tests/operators/tensor/core/at.cairo | 3 + .../operators/tensor/core/at/at_fp_test.cairo | 2 + .../core/at/at_fp_test/at_fp16x16_test.cairo | 77 +++++++++++++++++++ .../core/at/at_fp_test/at_fp8x23_test.cairo | 77 +++++++++++++++++++ .../tensor/core/at/at_i32_test.cairo | 73 ++++++++++++++++++ .../tensor/core/at/at_u32_test.cairo | 73 ++++++++++++++++++ 8 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 src/tests/operators/tensor/core.cairo create mode 100644 src/tests/operators/tensor/core/at.cairo create mode 100644 src/tests/operators/tensor/core/at/at_fp_test.cairo create mode 100644 src/tests/operators/tensor/core/at/at_fp_test/at_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/core/at/at_fp_test/at_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/core/at/at_i32_test.cairo create mode 100644 src/tests/operators/tensor/core/at/at_u32_test.cairo diff --git a/src/tests/operators/tensor.cairo b/src/tests/operators/tensor.cairo index df3dfc814..4fe917d84 100644 --- a/src/tests/operators/tensor.cairo +++ b/src/tests/operators/tensor.cairo @@ -1,3 +1,4 @@ mod tensor_test; mod math; -mod linalg; \ No newline at end of file +mod linalg; +mod core; \ No newline at end of file diff --git a/src/tests/operators/tensor/core.cairo b/src/tests/operators/tensor/core.cairo new file mode 100644 index 000000000..29a18432a --- /dev/null +++ b/src/tests/operators/tensor/core.cairo @@ -0,0 +1 @@ +mod at; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/at.cairo b/src/tests/operators/tensor/core/at.cairo new file mode 100644 index 000000000..bbb7ef326 --- /dev/null +++ b/src/tests/operators/tensor/core/at.cairo @@ -0,0 +1,3 @@ +mod at_u32_test; +mod at_i32_test; +mod at_fp_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/at/at_fp_test.cairo b/src/tests/operators/tensor/core/at/at_fp_test.cairo new file mode 100644 index 000000000..6fc2ff192 --- /dev/null +++ b/src/tests/operators/tensor/core/at/at_fp_test.cairo @@ -0,0 +1,2 @@ +mod at_fp8x23_test; +mod at_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/at/at_fp_test/at_fp16x16_test.cairo b/src/tests/operators/tensor/core/at/at_fp_test/at_fp16x16_test.cairo new file mode 100644 index 000000000..0a75cf5a3 --- /dev/null +++ b/src/tests/operators/tensor/core/at/at_fp_test/at_fp16x16_test.cairo @@ -0,0 +1,77 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = fp_tensor_1x3_helper(); + let mut indices = ArrayTrait::new(); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = fp_tensor_2x2_helper(); + + let mut indices = ArrayTrait::new(); + indices.append(1); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == FixedTrait::new_unscaled(3, false), 'result[4] = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = fp_tensor_2x2x2_helper(); + + let mut indices = ArrayTrait::new(); + indices.append(0); + indices.append(1); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + } +} diff --git a/src/tests/operators/tensor/core/at/at_fp_test/at_fp8x23_test.cairo b/src/tests/operators/tensor/core/at/at_fp_test/at_fp8x23_test.cairo new file mode 100644 index 000000000..dd0904bf6 --- /dev/null +++ b/src/tests/operators/tensor/core/at/at_fp_test/at_fp8x23_test.cairo @@ -0,0 +1,77 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = fp_tensor_1x3_helper(); + let mut indices = ArrayTrait::new(); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = fp_tensor_2x2_helper(); + + let mut indices = ArrayTrait::new(); + indices.append(1); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == FixedTrait::new_unscaled(3, false), 'result[4] = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = fp_tensor_2x2x2_helper(); + + let mut indices = ArrayTrait::new(); + indices.append(0); + indices.append(1); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + } +} diff --git a/src/tests/operators/tensor/core/at/at_i32_test.cairo b/src/tests/operators/tensor/core/at/at_i32_test.cairo new file mode 100644 index 000000000..2dd2d51ee --- /dev/null +++ b/src/tests/operators/tensor/core/at/at_i32_test.cairo @@ -0,0 +1,73 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = i32_tensor_1x3_helper(); + let mut indices = ArrayTrait::new(); + indices.append(1); + + let result = tensor.at(indices.span()).mag; + + assert(result == 1, 'result[2] = 1'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = i32_tensor_2x2_helper(); + + let mut indices = ArrayTrait::new(); + indices.append(1); + indices.append(1); + + let result = tensor.at(indices.span()).mag; + + assert(result == 3, 'result[4] = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = i32_tensor_2x2x2_helper(); + + let mut indices = ArrayTrait::new(); + indices.append(0); + indices.append(1); + indices.append(1); + + let result = tensor.at(indices.span()).mag; + + assert(result == 3, 'result[3] = 3'); + } +} diff --git a/src/tests/operators/tensor/core/at/at_u32_test.cairo b/src/tests/operators/tensor/core/at/at_u32_test.cairo new file mode 100644 index 000000000..175fe1c63 --- /dev/null +++ b/src/tests/operators/tensor/core/at/at_u32_test.cairo @@ -0,0 +1,73 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = u32_tensor_1x3_helper(); + let mut indices = ArrayTrait::new(); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == 1, 'result[2] = 1'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = u32_tensor_2x2_helper(); + + let mut indices = ArrayTrait::new(); + indices.append(1); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == 3, 'result[4] = 3'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = u32_tensor_2x2x2_helper(); + + let mut indices = ArrayTrait::new(); + indices.append(0); + indices.append(1); + indices.append(1); + + let result = tensor.at(indices.span()); + + assert(result == 3, 'result[3] = 3'); + } +} From b8678073e3ad1209db32616c6f94a32a15fc9bca Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 16:03:36 +0300 Subject: [PATCH 035/126] refactor tensor stride tests --- src/tests/operators/tensor.cairo | 1 - src/tests/operators/tensor/core.cairo | 3 +- src/tests/operators/tensor/core/stride.cairo | 3 + .../tensor/core/stride/stride_fp_test.cairo | 2 + .../stride_fp_test/stride_fp16x16_test.cairo | 68 +++ .../stride_fp_test/stride_fp8x23_test.cairo | 68 +++ .../tensor/core/stride/stride_i32_test.cairo | 68 +++ .../tensor/core/stride/stride_u32_test.cairo | 68 +++ src/tests/operators/tensor/tensor_test.cairo | 550 ------------------ 9 files changed, 279 insertions(+), 552 deletions(-) create mode 100644 src/tests/operators/tensor/core/stride.cairo create mode 100644 src/tests/operators/tensor/core/stride/stride_fp_test.cairo create mode 100644 src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/core/stride/stride_i32_test.cairo create mode 100644 src/tests/operators/tensor/core/stride/stride_u32_test.cairo delete mode 100644 src/tests/operators/tensor/tensor_test.cairo diff --git a/src/tests/operators/tensor.cairo b/src/tests/operators/tensor.cairo index 4fe917d84..18677472d 100644 --- a/src/tests/operators/tensor.cairo +++ b/src/tests/operators/tensor.cairo @@ -1,4 +1,3 @@ -mod tensor_test; mod math; mod linalg; mod core; \ No newline at end of file diff --git a/src/tests/operators/tensor/core.cairo b/src/tests/operators/tensor/core.cairo index 29a18432a..1b010a72f 100644 --- a/src/tests/operators/tensor/core.cairo +++ b/src/tests/operators/tensor/core.cairo @@ -1 +1,2 @@ -mod at; \ No newline at end of file +mod at; +mod stride; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/stride.cairo b/src/tests/operators/tensor/core/stride.cairo new file mode 100644 index 000000000..385e7bf22 --- /dev/null +++ b/src/tests/operators/tensor/core/stride.cairo @@ -0,0 +1,3 @@ +mod stride_u32_test; +mod stride_i32_test; +mod stride_fp_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/stride/stride_fp_test.cairo b/src/tests/operators/tensor/core/stride/stride_fp_test.cairo new file mode 100644 index 000000000..f9a50da68 --- /dev/null +++ b/src/tests/operators/tensor/core/stride/stride_fp_test.cairo @@ -0,0 +1,2 @@ +mod stride_fp8x23_test; +mod stride_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp16x16_test.cairo b/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp16x16_test.cairo new file mode 100644 index 000000000..f1fec401e --- /dev/null +++ b/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp16x16_test.cairo @@ -0,0 +1,68 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_stride() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 1, 'stride x = 1'); + assert(result.len() == 1, 'len = 1'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_stride() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 2, 'stride x = 2'); + assert(*result.at(1) == 1, 'stride y = 1'); + assert(result.len() == 2, 'len = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_stride() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 4, 'stride x = 4'); + assert(*result.at(1) == 2, 'stride y = 2'); + assert(*result.at(2) == 1, 'stride z = 1'); + assert(result.len() == 3, 'len = 3'); + } +} diff --git a/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp8x23_test.cairo b/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp8x23_test.cairo new file mode 100644 index 000000000..a7a7d670a --- /dev/null +++ b/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp8x23_test.cairo @@ -0,0 +1,68 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_stride() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 1, 'stride x = 1'); + assert(result.len() == 1, 'len = 1'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_stride() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 2, 'stride x = 2'); + assert(*result.at(1) == 1, 'stride y = 1'); + assert(result.len() == 2, 'len = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_stride() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 4, 'stride x = 4'); + assert(*result.at(1) == 2, 'stride y = 2'); + assert(*result.at(2) == 1, 'stride z = 1'); + assert(result.len() == 3, 'len = 3'); + } +} diff --git a/src/tests/operators/tensor/core/stride/stride_i32_test.cairo b/src/tests/operators/tensor/core/stride/stride_i32_test.cairo new file mode 100644 index 000000000..b9d7b4b6e --- /dev/null +++ b/src/tests/operators/tensor/core/stride/stride_i32_test.cairo @@ -0,0 +1,68 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_stride() { + let tensor = i32_tensor_1x3_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 1, 'stride x = 1'); + assert(result.len() == 1, 'len = 1'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = i32_tensor_2x2_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 2, 'stride x = 2'); + assert(*result.at(1) == 1, 'stride y = 1'); + assert(result.len() == 2, 'len = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 4, 'stride x = 4'); + assert(*result.at(1) == 2, 'stride y = 2'); + assert(*result.at(2) == 1, 'stride z = 1'); + assert(result.len() == 3, 'len = 3'); + } +} diff --git a/src/tests/operators/tensor/core/stride/stride_u32_test.cairo b/src/tests/operators/tensor/core/stride/stride_u32_test.cairo new file mode 100644 index 000000000..5fb0607ba --- /dev/null +++ b/src/tests/operators/tensor/core/stride/stride_u32_test.cairo @@ -0,0 +1,68 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_stride() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 1, 'stride x = 1'); + assert(result.len() == 1, 'len = 1'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = u32_tensor_2x2_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 2, 'stride x = 2'); + assert(*result.at(1) == 1, 'stride y = 1'); + assert(result.len() == 2, 'len = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.stride(); + assert(*result.at(0) == 4, 'stride x = 4'); + assert(*result.at(1) == 2, 'stride y = 2'); + assert(*result.at(2) == 1, 'stride z = 1'); + assert(result.len() == 3, 'len = 3'); + } +} diff --git a/src/tests/operators/tensor/tensor_test.cairo b/src/tests/operators/tensor/tensor_test.cairo deleted file mode 100644 index 9299dc2d2..000000000 --- a/src/tests/operators/tensor/tensor_test.cairo +++ /dev/null @@ -1,550 +0,0 @@ -use array::ArrayTrait; -use array::SpanTrait; -use traits::Into; - -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::tensor::implementations::impl_tensor_i32::{ - Tensor_i32, i32TensorAdd, i32TensorSub, i32TensorMul, i32TensorDiv -}; -use orion::operators::tensor::core::{TensorTrait, ExtraParams, ravel_index, unravel_index}; -use orion::tests::helpers::tensor::i32::{ - i32_tensor_2x2_helper, i32_tensor_3x2_helper, i32_tensor_2x3_helper, i32_tensor_2x2x2_helper, - i32_tensor_3x2x2_helper -}; - -#[test] -#[available_gas(2000000)] -#[should_panic] -fn wrong_shape_tensor_test() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0, false)); - data.append(IntegerTrait::new(1, false)); - data.append(IntegerTrait::new(2, false)); - - let extra = Option::::None(()); - - let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); -} - -#[test] -#[available_gas(2000000)] -fn at_tensor_test() { - let tensor = i32_tensor_2x2x2_helper(); - - let mut indices = ArrayTrait::new(); - indices.append(0); - indices.append(1); - indices.append(1); - - let result = tensor.at(indices.span()).mag; - - assert(result == 3, 'result[3] = 3'); -} - -#[test] -#[available_gas(2000000)] -fn stride_test() { - let tensor = i32_tensor_2x2x2_helper(); - let result = tensor.stride(); - assert(*result.at(0) == 4, 'stride x = 4'); - assert(*result.at(1) == 2, 'stride y = 2'); - assert(*result.at(2) == 1, 'stride z = 1'); -} - -#[test] -#[available_gas(2000000)] -fn ravel_index_test() { - // 1D - let mut shape = ArrayTrait::new(); - shape.append(5); - let mut indices = ArrayTrait::new(); - indices.append(2); - let result = ravel_index(shape.span(), indices.span()); - assert(result == 2, 'result = 2'); - - // 2D - let mut shape = ArrayTrait::new(); - shape.append(2); - shape.append(4); - let mut indices = ArrayTrait::new(); - indices.append(1); - indices.append(2); - let result = ravel_index(shape.span(), indices.span()); - assert(result == 6, 'result = 6'); - - // 3D - let mut shape = ArrayTrait::new(); - shape.append(2); - shape.append(4); - shape.append(6); - let mut indices = ArrayTrait::new(); - indices.append(1); - indices.append(3); - indices.append(0); - let result = ravel_index(shape.span(), indices.span()); - assert(result == 42, 'result = 42'); - - // 4D - let mut shape = ArrayTrait::new(); - shape.append(2); - shape.append(4); - shape.append(6); - shape.append(8); - let mut indices = ArrayTrait::new(); - indices.append(0); - indices.append(2); - indices.append(5); - indices.append(6); - let result = ravel_index(shape.span(), indices.span()); - assert(result == 142, 'result = 142'); -} - -#[test] -#[available_gas(2000000)] -fn unravel_index_test() { - // 1D - let mut shape = ArrayTrait::new(); - shape.append(5); - let result = unravel_index(2, shape.span()); - assert(*result.at(0) == 2, 'result[0] = 2'); - - // 2D - let mut shape = ArrayTrait::new(); - shape.append(2); - shape.append(4); - let result = unravel_index(6, shape.span()); - assert(*result.at(0) == 1, 'result[0] = 1'); - assert(*result.at(1) == 2, 'result[1] = 2'); - - // 3D - let mut shape = ArrayTrait::new(); - shape.append(2); - shape.append(4); - shape.append(6); - let result = unravel_index(42, shape.span()); - assert(*result.at(0) == 1, 'result[0] = 1'); - assert(*result.at(1) == 3, 'result[1] = 3'); - assert(*result.at(2) == 0, 'result[2] = 0'); - - // 4D - let mut shape = ArrayTrait::new(); - shape.append(2); - shape.append(4); - shape.append(6); - shape.append(8); - let result = unravel_index(142, shape.span()); - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 2, 'result[1] = 2'); - assert(*result.at(2) == 5, 'result[2] = 5'); - assert(*result.at(3) == 6, 'result[3] = 6'); -} - -#[test] -#[available_gas(20000000)] -fn add_tensor() { - let tensor_1 = i32_tensor_2x2x2_helper(); - let tensor_2 = i32_tensor_2x2x2_helper(); - - let result = (tensor_1 + tensor_2).data; - - assert((*result[0]).into() == 0, 'result[0] = 0'); - assert((*result[1]).into() == 2, 'result[1] = 2'); - assert((*result[2]).into() == 4, 'result[2] = 4'); - assert((*result[3]).into() == 6, 'result[3] = 6'); - assert((*result[4]).into() == 8, 'result[4] = 8'); - assert((*result[5]).into() == 10, 'result[5] = 10'); - assert((*result[6]).into() == 12, 'result[6] = 12'); - assert((*result[7]).into() == 14, 'result[7] = 14'); - - // broadcast operation - - let mut sizes = ArrayTrait::new(); - sizes.append(1); - sizes.append(2); - sizes.append(1); - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10, false)); - data.append(IntegerTrait::new(100, false)); - let extra = Option::::None(()); - let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = (tensor_1 + tensor_2).data; - - assert((*result[0]).into() == 10, 'result[0] = 10'); - assert((*result[1]).into() == 11, 'result[1] = 11'); - assert((*result[2]).into() == 102, 'result[2] = 102'); - assert((*result[3]).into() == 103, 'result[3] = 103'); - assert((*result[4]).into() == 14, 'result[4] = 14'); - assert((*result[5]).into() == 15, 'result[5] = 15'); - assert((*result[6]).into() == 106, 'result[6] = 106'); - assert((*result[7]).into() == 107, 'result[7] = 107'); - - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(1); - sizes.append(1); - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10, false)); - data.append(IntegerTrait::new(100, false)); - let extra = Option::::None(()); - let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = (tensor_1 + tensor_2).data; - - assert((*result[0]).into() == 10, 'result[0] = 10'); - assert((*result[1]).into() == 11, 'result[1] = 11'); - assert((*result[2]).into() == 12, 'result[2] = 12'); - assert((*result[3]).into() == 13, 'result[3] = 13'); - assert((*result[4]).into() == 104, 'result[4] = 104'); - assert((*result[5]).into() == 105, 'result[5] = 105'); - assert((*result[6]).into() == 106, 'result[6] = 106'); - assert((*result[7]).into() == 107, 'result[7] = 107'); - - let mut sizes = ArrayTrait::new(); - sizes.append(1); - sizes.append(1); - sizes.append(2); - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10, false)); - data.append(IntegerTrait::new(100, false)); - let extra = Option::::None(()); - let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = (tensor_1 + tensor_2).data; - - assert((*result[0]).into() == 10, 'result[0] = 10'); - assert((*result[1]).into() == 101, 'result[1] = 101'); - assert((*result[2]).into() == 12, 'result[2] = 12'); - assert((*result[3]).into() == 103, 'result[3] = 103'); - assert((*result[4]).into() == 14, 'result[4] = 14'); - assert((*result[5]).into() == 105, 'result[5] = 105'); - assert((*result[6]).into() == 16, 'result[6] = 16'); - assert((*result[7]).into() == 107, 'result[7] = 107'); -} - -#[test] -#[available_gas(200000000)] -fn sub_tensor() { - let tensor_1 = i32_tensor_2x2x2_helper(); - let tensor_2 = i32_tensor_2x2x2_helper(); - - let result = (tensor_1 - tensor_2).data; - - assert((*result[0]).into() == 0, 'result[0] = 0'); - assert((*result[1]).into() == 0, 'result[1] = 0'); - assert((*result[2]).into() == 0, 'result[2] = 0'); - assert((*result[3]).into() == 0, 'result[3] = 0'); - assert((*result[4]).into() == 0, 'result[4] = 0'); - assert((*result[5]).into() == 0, 'result[5] = 0'); - assert((*result[6]).into() == 0, 'result[6] = 0'); - assert((*result[7]).into() == 0, 'result[7] = 0'); - - // broadcast operation - - let mut sizes = ArrayTrait::new(); - sizes.append(1); - sizes.append(2); - sizes.append(1); - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(0, false)); - data.append(IntegerTrait::new(1, false)); - let extra = Option::::None(()); - let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = (tensor_1 - tensor_2).data; - - assert((*result[0]).into() == 0, 'result[0] = 0'); - assert((*result[1]).into() == 1, 'result[1] = 1'); - assert((*result[2]).into() == 1, 'result[2] = 1'); - assert((*result[3]).into() == 2, 'result[3] = 2'); - assert((*result[4]).into() == 4, 'result[4] = 4'); - assert((*result[5]).into() == 5, 'result[5] = 5'); - assert((*result[6]).into() == 5, 'result[6] = 5'); - assert((*result[7]).into() == 6, 'result[7] = 6'); -} - -#[test] -#[available_gas(20000000)] -fn mul_tensor() { - let tensor_1 = i32_tensor_2x2x2_helper(); - let tensor_2 = i32_tensor_2x2x2_helper(); - - let result = (tensor_1 * tensor_2).data; - - assert((*result[0]).into() == 0, 'result[0] = 0'); - assert((*result[1]).into() == 1, 'result[1] = 1'); - assert((*result[2]).into() == 4, 'result[2] = 4'); - assert((*result[3]).into() == 9, 'result[3] = 9'); - assert((*result[4]).into() == 16, 'result[4] = 16'); - assert((*result[5]).into() == 25, 'result[5] = 25'); - assert((*result[6]).into() == 36, 'result[6] = 36'); - assert((*result[7]).into() == 49, 'result[7] = 49'); - - // broadcast operation - - let mut sizes = ArrayTrait::new(); - sizes.append(1); - sizes.append(2); - sizes.append(1); - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10, false)); - data.append(IntegerTrait::new(100, false)); - let extra = Option::::None(()); - let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = (tensor_1 * tensor_2).data; - - assert((*result[0]).into() == 0, 'result[0] = 0'); - assert((*result[1]).into() == 10, 'result[1] = 10'); - assert((*result[2]).into() == 200, 'result[2] = 200'); - assert((*result[3]).into() == 300, 'result[3] = 300'); - assert((*result[4]).into() == 40, 'result[4] = 40'); - assert((*result[5]).into() == 50, 'result[5] = 50'); - assert((*result[6]).into() == 600, 'result[6] = 600'); - assert((*result[7]).into() == 700, 'result[7] = 700'); -} - -#[test] -#[available_gas(20000000)] -fn div_tensor() { - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(100, false)); - data.append(IntegerTrait::new(200, false)); - data.append(IntegerTrait::new(300, false)); - data.append(IntegerTrait::new(400, false)); - data.append(IntegerTrait::new(500, false)); - data.append(IntegerTrait::new(600, false)); - data.append(IntegerTrait::new(700, false)); - data.append(IntegerTrait::new(800, false)); - let extra = Option::::None(()); - let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); - - let mut sizes = ArrayTrait::new(); - sizes.append(2); - sizes.append(2); - sizes.append(2); - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(100, false)); - data.append(IntegerTrait::new(200, false)); - data.append(IntegerTrait::new(300, false)); - data.append(IntegerTrait::new(400, false)); - data.append(IntegerTrait::new(500, false)); - data.append(IntegerTrait::new(600, false)); - data.append(IntegerTrait::new(700, false)); - data.append(IntegerTrait::new(800, false)); - let extra = Option::::None(()); - let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = (tensor_1 / tensor_2).data; - - assert((*result[0]).into() == 1, 'result[0] = 1'); - assert((*result[1]).into() == 1, 'result[1] = 1'); - assert((*result[2]).into() == 1, 'result[2] = 1'); - assert((*result[3]).into() == 1, 'result[3] = 1'); - assert((*result[4]).into() == 1, 'result[4] = 1'); - assert((*result[5]).into() == 1, 'result[5] = 1'); - assert((*result[6]).into() == 1, 'result[6] = 1'); - assert((*result[7]).into() == 1, 'result[7] = 1'); - - // broadcast operation - - let mut sizes = ArrayTrait::new(); - sizes.append(1); - sizes.append(2); - sizes.append(1); - let mut data = ArrayTrait::new(); - data.append(IntegerTrait::new(10, false)); - data.append(IntegerTrait::new(100, false)); - let extra = Option::::None(()); - let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); - - let result = (tensor_1 / tensor_2).data; - - assert((*result[0]).into() == 10, 'result[0] = 10'); - assert((*result[1]).into() == 20, 'result[1] = 20'); - assert((*result[2]).into() == 3, 'result[2] = 3'); - assert((*result[3]).into() == 4, 'result[3] = 4'); - assert((*result[4]).into() == 50, 'result[4] = 50'); - assert((*result[5]).into() == 60, 'result[5] = 60'); - assert((*result[6]).into() == 7, 'result[6] = 7'); - assert((*result[7]).into() == 8, 'result[7] = 8'); -} - -#[test] -#[available_gas(200000000)] -fn tensor_transpose_2D() { - let mut axes: Array = ArrayTrait::new(); - axes.append(1); - axes.append(0); - - let tensor = i32_tensor_2x2_helper(); - - let result = tensor.transpose(axes.span()); - - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 2, 'result[1] = 2'); - assert((*result.data[2]).into() == 1, 'result[2] = 1'); - assert((*result.data[3]).into() == 3, 'result[3] = 3'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - - let tensor = i32_tensor_3x2_helper(); - - let result = tensor.transpose(axes.span()); - - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 2, 'result[1] = 2'); - assert((*result.data[2]).into() == 4, 'result[2] = 4'); - assert((*result.data[3]).into() == 1, 'result[3] = 1'); - assert((*result.data[4]).into() == 3, 'result[4] = 3'); - assert((*result.data[5]).into() == 5, 'result[5] = 5'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 3, 'shape[1] = 3'); - - let tensor = i32_tensor_2x3_helper(); - - let result = tensor.transpose(axes.span()); - - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 3, 'result[1] = 3'); - assert((*result.data[2]).into() == 1, 'result[2] = 1'); - assert((*result.data[3]).into() == 4, 'result[3] = 4'); - assert((*result.data[4]).into() == 2, 'result[4] = 2'); - assert((*result.data[5]).into() == 5, 'result[5] = 5'); - assert(*result.shape.at(0) == 3, 'shape[0] = 3'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); -} - -#[test] -#[available_gas(200000000)] -fn tensor_transpose_3D() { - let tensor = i32_tensor_2x2x2_helper(); - - let mut axes: Array = ArrayTrait::new(); - axes.append(1); - axes.append(2); - axes.append(0); - - let result = tensor.transpose(axes.span()).data; - - assert((*result[0]).into() == 0, 'result[0] = 0'); - assert((*result[1]).into() == 4, 'result[1] = 4'); - assert((*result[2]).into() == 1, 'result[2] = 1'); - assert((*result[3]).into() == 5, 'result[3] = 5'); - assert((*result[4]).into() == 2, 'result[4] = 2'); - assert((*result[5]).into() == 6, 'result[5] = 6'); - assert((*result[6]).into() == 3, 'result[6] = 3'); - assert((*result[7]).into() == 7, 'result[7] = 7'); - - let mut axes: Array = ArrayTrait::new(); - axes.append(2); - axes.append(1); - axes.append(0); - - let result = tensor.transpose(axes.span()).data; - - assert((*result[0]).into() == 0, 'result[0] = 0'); - assert((*result[1]).into() == 4, 'result[1] = 4'); - assert((*result[2]).into() == 2, 'result[2] = 2'); - assert((*result[3]).into() == 6, 'result[3] = 6'); - assert((*result[4]).into() == 1, 'result[4] = 1'); - assert((*result[5]).into() == 5, 'result[5] = 5'); - assert((*result[6]).into() == 3, 'result[6] = 3'); - assert((*result[7]).into() == 7, 'result[7] = 7'); - - let mut axes: Array = ArrayTrait::new(); - axes.append(0); - axes.append(2); - axes.append(1); - - let result = tensor.transpose(axes.span()).data; - - assert((*result[0]).into() == 0, 'result[0] = 0'); - assert((*result[1]).into() == 2, 'result[1] = 2'); - assert((*result[2]).into() == 1, 'result[2] = 1'); - assert((*result[3]).into() == 3, 'result[3] = 3'); - assert((*result[4]).into() == 4, 'result[4] = 4'); - assert((*result[5]).into() == 6, 'result[5] = 6'); - assert((*result[6]).into() == 5, 'result[6] = 5'); - assert((*result[7]).into() == 7, 'result[7] = 7'); - - let tensor = i32_tensor_3x2x2_helper(); - - let mut axes: Array = ArrayTrait::new(); - axes.append(1); - axes.append(2); - axes.append(0); - - let result = tensor.transpose(axes.span()); - - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 4, 'result[1] = 4'); - assert((*result.data[2]).into() == 8, 'result[2] = 8'); - assert((*result.data[3]).into() == 1, 'result[3] = 1'); - assert((*result.data[4]).into() == 5, 'result[4] = 5'); - assert((*result.data[5]).into() == 9, 'result[5] = 9'); - assert((*result.data[6]).into() == 2, 'result[6] = 2'); - assert((*result.data[7]).into() == 6, 'result[7] = 6'); - assert((*result.data[8]).into() == 10, 'result[7] = 10'); - assert((*result.data[9]).into() == 3, 'result[7] = 3'); - assert((*result.data[10]).into() == 7, 'result[7] = 7'); - assert((*result.data[11]).into() == 11, 'result[7] = 11'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 3, 'shape[2] = 3'); - - let mut axes: Array = ArrayTrait::new(); - axes.append(2); - axes.append(1); - axes.append(0); - - let result = tensor.transpose(axes.span()); - - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 4, 'result[1] = 4'); - assert((*result.data[2]).into() == 8, 'result[2] = 8'); - assert((*result.data[3]).into() == 2, 'result[3] = 2'); - assert((*result.data[4]).into() == 6, 'result[4] = 6'); - assert((*result.data[5]).into() == 10, 'result[5] = 10'); - assert((*result.data[6]).into() == 1, 'result[6] = 1'); - assert((*result.data[7]).into() == 5, 'result[7] = 5'); - assert((*result.data[8]).into() == 9, 'result[7] = 9'); - assert((*result.data[9]).into() == 3, 'result[7] = 3'); - assert((*result.data[10]).into() == 7, 'result[7] = 7'); - assert((*result.data[11]).into() == 11, 'result[7] = 11'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 3, 'shape[2] = 3'); - - let mut axes: Array = ArrayTrait::new(); - axes.append(0); - axes.append(2); - axes.append(1); - - let result = tensor.transpose(axes.span()); - - assert((*result.data[0]).into() == 0, 'result[0] = 0'); - assert((*result.data[1]).into() == 2, 'result[1] = 2'); - assert((*result.data[2]).into() == 1, 'result[2] = 1'); - assert((*result.data[3]).into() == 3, 'result[3] = 3'); - assert((*result.data[4]).into() == 4, 'result[4] = 4'); - assert((*result.data[5]).into() == 6, 'result[5] = 6'); - assert((*result.data[6]).into() == 5, 'result[6] = 5'); - assert((*result.data[7]).into() == 7, 'result[7] = 7'); - assert((*result.data[8]).into() == 8, 'result[7] = 8'); - assert((*result.data[9]).into() == 10, 'result[7] = 10'); - assert((*result.data[10]).into() == 9, 'result[7] = 9'); - assert((*result.data[11]).into() == 11, 'result[7] = 11'); - assert(*result.shape.at(0) == 3, 'shape[0] = 3'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 2, 'shape[2] = 2'); -} From 9241833314bb827ec27b35e06c0b69824d38f089 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 16:09:52 +0300 Subject: [PATCH 036/126] refactor ravel_index tests --- src/tests/operators/tensor/core.cairo | 3 +- .../operators/tensor/core/ravel_index.cairo | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/tests/operators/tensor/core/ravel_index.cairo diff --git a/src/tests/operators/tensor/core.cairo b/src/tests/operators/tensor/core.cairo index 1b010a72f..1807b6364 100644 --- a/src/tests/operators/tensor/core.cairo +++ b/src/tests/operators/tensor/core.cairo @@ -1,2 +1,3 @@ mod at; -mod stride; \ No newline at end of file +mod stride; +mod ravel_index; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/ravel_index.cairo b/src/tests/operators/tensor/core/ravel_index.cairo new file mode 100644 index 000000000..dec634507 --- /dev/null +++ b/src/tests/operators/tensor/core/ravel_index.cairo @@ -0,0 +1,63 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use orion::operators::tensor::core::{ravel_index}; + + #[test] + #[available_gas(2000000)] + fn tensor_ravel_index() { + let mut shape = ArrayTrait::new(); + shape.append(5); + let mut indices = ArrayTrait::new(); + indices.append(2); + let result = ravel_index(shape.span(), indices.span()); + assert(result == 2, 'result = 2'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use orion::operators::tensor::core::{ravel_index}; + + #[test] + #[available_gas(2000000)] + fn tensor_ravel_index() { + let mut shape = ArrayTrait::new(); + shape.append(2); + shape.append(4); + let mut indices = ArrayTrait::new(); + indices.append(1); + indices.append(2); + let result = ravel_index(shape.span(), indices.span()); + assert(result == 6, 'result = 6'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use orion::operators::tensor::core::{ravel_index}; + + + #[test] + #[available_gas(2000000)] + fn tensor_at() { + let mut shape = ArrayTrait::new(); + shape.append(2); + shape.append(4); + shape.append(6); + let mut indices = ArrayTrait::new(); + indices.append(1); + indices.append(3); + indices.append(0); + let result = ravel_index(shape.span(), indices.span()); + assert(result == 42, 'result = 42'); + } +} From 93dbb4409339c0e13ac61c330213b1495851e499 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 16:12:50 +0300 Subject: [PATCH 037/126] refactor unravel_index tests --- src/tests/operators/tensor/core.cairo | 3 +- .../operators/tensor/core/ravel_index.cairo | 2 +- .../operators/tensor/core/unravel_index.cairo | 63 +++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/tests/operators/tensor/core/unravel_index.cairo diff --git a/src/tests/operators/tensor/core.cairo b/src/tests/operators/tensor/core.cairo index 1807b6364..113893d9c 100644 --- a/src/tests/operators/tensor/core.cairo +++ b/src/tests/operators/tensor/core.cairo @@ -1,3 +1,4 @@ mod at; mod stride; -mod ravel_index; \ No newline at end of file +mod ravel_index; +mod unravel_index; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/ravel_index.cairo b/src/tests/operators/tensor/core/ravel_index.cairo index dec634507..caeb9046e 100644 --- a/src/tests/operators/tensor/core/ravel_index.cairo +++ b/src/tests/operators/tensor/core/ravel_index.cairo @@ -48,7 +48,7 @@ mod tensor_3D { #[test] #[available_gas(2000000)] - fn tensor_at() { + fn tensor_ravel_index() { let mut shape = ArrayTrait::new(); shape.append(2); shape.append(4); diff --git a/src/tests/operators/tensor/core/unravel_index.cairo b/src/tests/operators/tensor/core/unravel_index.cairo new file mode 100644 index 000000000..27a8ee9c8 --- /dev/null +++ b/src/tests/operators/tensor/core/unravel_index.cairo @@ -0,0 +1,63 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{unravel_index}; + + #[test] + #[available_gas(2000000)] + fn tensor_unravel_index() { + let mut shape = ArrayTrait::new(); + shape.append(5); + let result = unravel_index(2, shape.span()); + assert(*result.at(0) == 2, 'result[0] = 2'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{unravel_index}; + + #[test] + #[available_gas(2000000)] + fn tensor_unravel_index() { + let mut shape = ArrayTrait::new(); + shape.append(2); + shape.append(4); + let result = unravel_index(6, shape.span()); + assert(*result.at(0) == 1, 'result[0] = 1'); + assert(*result.at(1) == 2, 'result[1] = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{unravel_index}; + + + #[test] + #[available_gas(2000000)] + fn tensor_unravel_index() { + let mut shape = ArrayTrait::new(); + shape.append(2); + shape.append(4); + shape.append(6); + let result = unravel_index(42, shape.span()); + assert(*result.at(0) == 1, 'result[0] = 1'); + assert(*result.at(1) == 3, 'result[1] = 3'); + assert(*result.at(2) == 0, 'result[2] = 0'); + } +} From 532220e7fe596093a15a22c386780dc794b0e3ca Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 17:26:58 +0300 Subject: [PATCH 038/126] refactor tensor arithmetic tests --- src/tests/operators/tensor/math.cairo | 1 + .../tensor/math/abs/abs_u32_test.cairo | 8 - .../operators/tensor/math/arithmetic.cairo | 3 + .../math/arithmetic/arithmetic_fp_test.cairo | 2 + .../arithmetic_fp16x16_test.cairo | 702 +++++++++++++++++ .../arithmetic_fp8x23_test.cairo | 721 ++++++++++++++++++ .../math/arithmetic/arithmetic_i32_test.cairo | 672 ++++++++++++++++ .../math/arithmetic/arithmetic_u32_test.cairo | 660 ++++++++++++++++ 8 files changed, 2761 insertions(+), 8 deletions(-) create mode 100644 src/tests/operators/tensor/math/arithmetic.cairo create mode 100644 src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test.cairo create mode 100644 src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/math/arithmetic/arithmetic_i32_test.cairo create mode 100644 src/tests/operators/tensor/math/arithmetic/arithmetic_u32_test.cairo diff --git a/src/tests/operators/tensor/math.cairo b/src/tests/operators/tensor/math.cairo index 8953d0ad3..826039c61 100644 --- a/src/tests/operators/tensor/math.cairo +++ b/src/tests/operators/tensor/math.cairo @@ -12,3 +12,4 @@ mod less_equal; mod abs; mod ceil; mod ln; +mod arithmetic; diff --git a/src/tests/operators/tensor/math/abs/abs_u32_test.cairo b/src/tests/operators/tensor/math/abs/abs_u32_test.cairo index 0a15b1c6e..1252199f3 100644 --- a/src/tests/operators/tensor/math/abs/abs_u32_test.cairo +++ b/src/tests/operators/tensor/math/abs/abs_u32_test.cairo @@ -1,11 +1,3 @@ -use array::SpanTrait; -use array::ArrayTrait; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::tests::helpers::tensor::u32::{ - u32_tensor_1x3_helper, u32_tensor_2x2_helper, u32_tensor_2x2x2_helper -}; - // ===== 1D ===== // #[cfg(test)] diff --git a/src/tests/operators/tensor/math/arithmetic.cairo b/src/tests/operators/tensor/math/arithmetic.cairo new file mode 100644 index 000000000..e9c19950d --- /dev/null +++ b/src/tests/operators/tensor/math/arithmetic.cairo @@ -0,0 +1,3 @@ +mod arithmetic_u32_test; +mod arithmetic_i32_test; +mod arithmetic_fp_test; diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test.cairo new file mode 100644 index 000000000..41a4c32d7 --- /dev/null +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test.cairo @@ -0,0 +1,2 @@ +mod arithmetic_fp8x23_test; +mod arithmetic_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp16x16_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp16x16_test.cairo new file mode 100644 index 000000000..7d9c61c71 --- /dev/null +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp16x16_test.cairo @@ -0,0 +1,702 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::FixedTypeTensorAdd; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::FixedTypeTensorSub; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::FixedTypeTensorMul; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorDiv, Tensor_fp + }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams, ravel_index, unravel_index}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorAdd, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = fp_tensor_2x2_helper(); + let tensor_2 = fp_tensor_2x2_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_add_broadcast() { + let tensor_1 = fp_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); + assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result.at(2) == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); + assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorSub, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = fp_tensor_2x2_helper(); + let tensor_2 = fp_tensor_2x2_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result.at(3) == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_sub_broadcast() { + let tensor_1 = fp_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result.at(2) == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorMul, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = fp_tensor_2x2_helper(); + let tensor_2 = fp_tensor_2x2_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.at(3) == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_mul_broadcast() { + let tensor_1 = fp_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(100, false), 'result[1] = 100'); + assert(*result.at(2) == FixedTrait::new_unscaled(20, false), 'result[2] = 20'); + assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); + assert(*result.at(2) == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); + assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorDiv, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + data.append(FixedTrait::new_unscaled(300, false)); + data.append(FixedTrait::new_unscaled(400, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_div_broadcast() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + data.append(FixedTrait::new_unscaled(300, false)); + data.append(FixedTrait::new_unscaled(400, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(30, false), 'result[2] = 30'); + assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); + assert(*result.at(2) == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); + assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorAdd, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = fp_tensor_2x2x2_helper(); + let tensor_2 = fp_tensor_2x2x2_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result.at(4) == FixedTrait::new_unscaled(8, false), 'result[4] = 8'); + assert(*result.at(5) == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); + assert(*result.at(6) == FixedTrait::new_unscaled(12, false), 'result[6] = 12'); + assert(*result.at(7) == FixedTrait::new_unscaled(14, false), 'result[7] = 14'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_add_broadcast() { + let tensor_1 = fp_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result.at(2) == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); + assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result.at(4) == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); + assert(*result.at(5) == FixedTrait::new_unscaled(15, false), 'result[5] = 15'); + assert(*result.at(6) == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); + assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.at(3) == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); + assert(*result.at(4) == FixedTrait::new_unscaled(104, false), 'result[4] = 104'); + assert(*result.at(5) == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); + assert(*result.at(6) == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); + assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); + assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result.at(4) == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); + assert(*result.at(5) == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); + assert(*result.at(6) == FixedTrait::new_unscaled(16, false), 'result[6] = 16'); + assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorSub, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = fp_tensor_2x2x2_helper(); + let tensor_2 = fp_tensor_2x2x2_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result.at(3) == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); + assert(*result.at(4) == FixedTrait::new_unscaled(0, false), 'result[4] = 0'); + assert(*result.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.at(6) == FixedTrait::new_unscaled(0, false), 'result[6] = 0'); + assert(*result.at(7) == FixedTrait::new_unscaled(0, false), 'result[7] = 0'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_sub_broadcast() { + let tensor_1 = fp_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result.at(7) == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorMul, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = fp_tensor_2x2x2_helper(); + let tensor_2 = fp_tensor_2x2x2_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.at(3) == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); + assert(*result.at(4) == FixedTrait::new_unscaled(16, false), 'result[4] = 16'); + assert(*result.at(5) == FixedTrait::new_unscaled(25, false), 'result[5] = 25'); + assert(*result.at(6) == FixedTrait::new_unscaled(36, false), 'result[6] = 36'); + assert(*result.at(7) == FixedTrait::new_unscaled(49, false), 'result[7] = 49'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_mul_broadcast() { + let tensor_1 = fp_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); + assert(*result.at(2) == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); + assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + assert(*result.at(4) == FixedTrait::new_unscaled(40, false), 'result[4] = 40'); + assert(*result.at(5) == FixedTrait::new_unscaled(50, false), 'result[5] = 50'); + assert(*result.at(6) == FixedTrait::new_unscaled(600, false), 'result[6] = 600'); + assert(*result.at(7) == FixedTrait::new_unscaled(700, false), 'result[7] = 700'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorDiv, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + data.append(FixedTrait::new_unscaled(300, false)); + data.append(FixedTrait::new_unscaled(400, false)); + data.append(FixedTrait::new_unscaled(500, false)); + data.append(FixedTrait::new_unscaled(600, false)); + data.append(FixedTrait::new_unscaled(700, false)); + data.append(FixedTrait::new_unscaled(800, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.at(5) == FixedTrait::new_unscaled(1, false), 'result[5] = 1'); + assert(*result.at(6) == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); + assert(*result.at(7) == FixedTrait::new_unscaled(1, false), 'result[7] = 1'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_div_broadcast() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + data.append(FixedTrait::new_unscaled(300, false)); + data.append(FixedTrait::new_unscaled(400, false)); + data.append(FixedTrait::new_unscaled(500, false)); + data.append(FixedTrait::new_unscaled(600, false)); + data.append(FixedTrait::new_unscaled(700, false)); + data.append(FixedTrait::new_unscaled(800, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); + assert(*result.at(2) == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); + assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result.at(4) == FixedTrait::new_unscaled(50, false), 'result[4] = 50'); + assert(*result.at(5) == FixedTrait::new_unscaled(60, false), 'result[5] = 60'); + assert(*result.at(6) == FixedTrait::new_unscaled(7, false), 'result[6] = 7'); + assert(*result.at(7) == FixedTrait::new_unscaled(8, false), 'result[7] = 8'); + } + } +} diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp8x23_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp8x23_test.cairo new file mode 100644 index 000000000..0f779e5b4 --- /dev/null +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp8x23_test.cairo @@ -0,0 +1,721 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::FixedTypeTensorAdd; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::FixedTypeTensorSub; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::FixedTypeTensorMul; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = fp_tensor_1x3_helper(); + let tensor_2 = fp_tensor_1x3_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorDiv, Tensor_fp + }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams, ravel_index, unravel_index}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorAdd, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = fp_tensor_2x2_helper(); + let tensor_2 = fp_tensor_2x2_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_add_broadcast() { + let tensor_1 = fp_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); + assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result.at(2) == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); + assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorSub, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = fp_tensor_2x2_helper(); + let tensor_2 = fp_tensor_2x2_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result.at(3) == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_sub_broadcast() { + let tensor_1 = fp_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result.at(2) == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorMul, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = fp_tensor_2x2_helper(); + let tensor_2 = fp_tensor_2x2_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.at(3) == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_mul_broadcast() { + let tensor_1 = fp_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(100, false), 'result[1] = 100'); + assert(*result.at(2) == FixedTrait::new_unscaled(20, false), 'result[2] = 20'); + assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); + assert(*result.at(2) == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); + assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorDiv, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + data.append(FixedTrait::new_unscaled(300, false)); + data.append(FixedTrait::new_unscaled(400, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_div_broadcast() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + data.append(FixedTrait::new_unscaled(300, false)); + data.append(FixedTrait::new_unscaled(400, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(30, false), 'result[2] = 30'); + assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); + assert(*result.at(2) == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); + assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorAdd, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = fp_tensor_2x2x2_helper(); + let tensor_2 = fp_tensor_2x2x2_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result.at(4) == FixedTrait::new_unscaled(8, false), 'result[4] = 8'); + assert(*result.at(5) == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); + assert(*result.at(6) == FixedTrait::new_unscaled(12, false), 'result[6] = 12'); + assert(*result.at(7) == FixedTrait::new_unscaled(14, false), 'result[7] = 14'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_add_broadcast() { + let tensor_1 = fp_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result.at(2) == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); + assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result.at(4) == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); + assert(*result.at(5) == FixedTrait::new_unscaled(15, false), 'result[5] = 15'); + assert(*result.at(6) == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); + assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.at(3) == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); + assert(*result.at(4) == FixedTrait::new_unscaled(104, false), 'result[4] = 104'); + assert(*result.at(5) == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); + assert(*result.at(6) == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); + assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); + assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result.at(4) == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); + assert(*result.at(5) == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); + assert(*result.at(6) == FixedTrait::new_unscaled(16, false), 'result[6] = 16'); + assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorSub, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = fp_tensor_2x2x2_helper(); + let tensor_2 = fp_tensor_2x2x2_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result.at(3) == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); + assert(*result.at(4) == FixedTrait::new_unscaled(0, false), 'result[4] = 0'); + assert(*result.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.at(6) == FixedTrait::new_unscaled(0, false), 'result[6] = 0'); + assert(*result.at(7) == FixedTrait::new_unscaled(0, false), 'result[7] = 0'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_sub_broadcast() { + let tensor_1 = fp_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(0, false)); + data.append(FixedTrait::new_unscaled(1, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result.at(7) == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorMul, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = fp_tensor_2x2x2_helper(); + let tensor_2 = fp_tensor_2x2x2_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.at(3) == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); + assert(*result.at(4) == FixedTrait::new_unscaled(16, false), 'result[4] = 16'); + assert(*result.at(5) == FixedTrait::new_unscaled(25, false), 'result[5] = 25'); + assert(*result.at(6) == FixedTrait::new_unscaled(36, false), 'result[6] = 36'); + assert(*result.at(7) == FixedTrait::new_unscaled(49, false), 'result[7] = 49'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_mul_broadcast() { + let tensor_1 = fp_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); + assert(*result.at(2) == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); + assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + assert(*result.at(4) == FixedTrait::new_unscaled(40, false), 'result[4] = 40'); + assert(*result.at(5) == FixedTrait::new_unscaled(50, false), 'result[5] = 50'); + assert(*result.at(6) == FixedTrait::new_unscaled(600, false), 'result[6] = 600'); + assert(*result.at(7) == FixedTrait::new_unscaled(700, false), 'result[7] = 700'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::{ + FixedTypeTensorDiv, Tensor_fp + }; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + data.append(FixedTrait::new_unscaled(300, false)); + data.append(FixedTrait::new_unscaled(400, false)); + data.append(FixedTrait::new_unscaled(500, false)); + data.append(FixedTrait::new_unscaled(600, false)); + data.append(FixedTrait::new_unscaled(700, false)); + data.append(FixedTrait::new_unscaled(800, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.at(5) == FixedTrait::new_unscaled(1, false), 'result[5] = 1'); + assert(*result.at(6) == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); + assert(*result.at(7) == FixedTrait::new_unscaled(1, false), 'result[7] = 1'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_div_broadcast() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(100, false)); + data.append(FixedTrait::new_unscaled(200, false)); + data.append(FixedTrait::new_unscaled(300, false)); + data.append(FixedTrait::new_unscaled(400, false)); + data.append(FixedTrait::new_unscaled(500, false)); + data.append(FixedTrait::new_unscaled(600, false)); + data.append(FixedTrait::new_unscaled(700, false)); + data.append(FixedTrait::new_unscaled(800, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(FixedTrait::new_unscaled(10, false)); + data.append(FixedTrait::new_unscaled(100, false)); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result.at(1) == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); + assert(*result.at(2) == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); + assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result.at(4) == FixedTrait::new_unscaled(50, false), 'result[4] = 50'); + assert(*result.at(5) == FixedTrait::new_unscaled(60, false), 'result[5] = 60'); + assert(*result.at(6) == FixedTrait::new_unscaled(7, false), 'result[6] = 7'); + assert(*result.at(7) == FixedTrait::new_unscaled(8, false), 'result[7] = 8'); + } + } +} diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_i32_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_i32_test.cairo new file mode 100644 index 000000000..74a110e6d --- /dev/null +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_i32_test.cairo @@ -0,0 +1,672 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::i32TensorAdd; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = i32_tensor_1x3_helper(); + let tensor_2 = i32_tensor_1x3_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(2, false), 'result[1] = 2'); + assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::i32TensorSub; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = i32_tensor_1x3_helper(); + let tensor_2 = i32_tensor_1x3_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(0, false), 'result[1] = 0'); + assert(*result.at(2) == IntegerTrait::new(0, false), 'result[2] = 0'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::i32TensorMul; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = i32_tensor_1x3_helper(); + let tensor_2 = i32_tensor_1x3_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorDiv, Tensor_i32}; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams, ravel_index, unravel_index}; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(200, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(1, false), 'result[0] = 1'); + assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorAdd, Tensor_i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = i32_tensor_2x2_helper(); + let tensor_2 = i32_tensor_2x2_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(2, false), 'result[1] = 2'); + assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result.at(3) == IntegerTrait::new(6, false), 'result[3] = 6'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_add_broadcast() { + let tensor_1 = i32_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result.at(1) == IntegerTrait::new(101, false), 'result[1] = 101'); + assert(*result.at(2) == IntegerTrait::new(12, false), 'result[2] = 12'); + assert(*result.at(3) == IntegerTrait::new(103, false), 'result[3] = 103'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result.at(1) == IntegerTrait::new(11, false), 'result[1] = 11'); + assert(*result.at(2) == IntegerTrait::new(102, false), 'result[2] = 102'); + assert(*result.at(3) == IntegerTrait::new(103, false), 'result[3] = 103'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorSub, Tensor_i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = i32_tensor_2x2_helper(); + let tensor_2 = i32_tensor_2x2_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(0, false), 'result[1] = 0'); + assert(*result.at(2) == IntegerTrait::new(0, false), 'result[2] = 0'); + assert(*result.at(3) == IntegerTrait::new(0, false), 'result[3] = 0'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_sub_broadcast() { + let tensor_1 = i32_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(0, false), 'result[1] = 0'); + assert(*result.at(2) == IntegerTrait::new(2, false), 'result[2] = 2'); + assert(*result.at(3) == IntegerTrait::new(2, false), 'result[3] = 2'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result.at(2) == IntegerTrait::new(1, false), 'result[2] = 1'); + assert(*result.at(3) == IntegerTrait::new(2, false), 'result[3] = 2'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorMul, Tensor_i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = i32_tensor_2x2_helper(); + let tensor_2 = i32_tensor_2x2_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result.at(3) == IntegerTrait::new(9, false), 'result[3] = 9'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_mul_broadcast() { + let tensor_1 = i32_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(100, false), 'result[1] = 100'); + assert(*result.at(2) == IntegerTrait::new(20, false), 'result[2] = 20'); + assert(*result.at(3) == IntegerTrait::new(300, false), 'result[3] = 300'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(10, false), 'result[1] = 10'); + assert(*result.at(2) == IntegerTrait::new(200, false), 'result[2] = 200'); + assert(*result.at(3) == IntegerTrait::new(300, false), 'result[3] = 300'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorDiv, Tensor_i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(200, false)); + data.append(IntegerTrait::new(300, false)); + data.append(IntegerTrait::new(400, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(1, false), 'result[0] = 1'); + assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result.at(2) == IntegerTrait::new(1, false), 'result[2] = 1'); + assert(*result.at(3) == IntegerTrait::new(1, false), 'result[3] = 1'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_div_broadcast() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(200, false)); + data.append(IntegerTrait::new(300, false)); + data.append(IntegerTrait::new(400, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result.at(1) == IntegerTrait::new(2, false), 'result[1] = 2'); + assert(*result.at(2) == IntegerTrait::new(30, false), 'result[2] = 30'); + assert(*result.at(3) == IntegerTrait::new(4, false), 'result[3] = 4'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result.at(1) == IntegerTrait::new(20, false), 'result[1] = 20'); + assert(*result.at(2) == IntegerTrait::new(3, false), 'result[2] = 3'); + assert(*result.at(3) == IntegerTrait::new(4, false), 'result[3] = 4'); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorAdd, Tensor_i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = i32_tensor_2x2x2_helper(); + let tensor_2 = i32_tensor_2x2x2_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(2, false), 'result[1] = 2'); + assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result.at(3) == IntegerTrait::new(6, false), 'result[3] = 6'); + assert(*result.at(4) == IntegerTrait::new(8, false), 'result[4] = 8'); + assert(*result.at(5) == IntegerTrait::new(10, false), 'result[5] = 10'); + assert(*result.at(6) == IntegerTrait::new(12, false), 'result[6] = 12'); + assert(*result.at(7) == IntegerTrait::new(14, false), 'result[7] = 14'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_add_broadcast() { + let tensor_1 = i32_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result.at(1) == IntegerTrait::new(11, false), 'result[1] = 11'); + assert(*result.at(2) == IntegerTrait::new(102, false), 'result[2] = 102'); + assert(*result.at(3) == IntegerTrait::new(103, false), 'result[3] = 103'); + assert(*result.at(4) == IntegerTrait::new(14, false), 'result[4] = 14'); + assert(*result.at(5) == IntegerTrait::new(15, false), 'result[5] = 15'); + assert(*result.at(6) == IntegerTrait::new(106, false), 'result[6] = 106'); + assert(*result.at(7) == IntegerTrait::new(107, false), 'result[7] = 107'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result.at(1) == IntegerTrait::new(11, false), 'result[1] = 11'); + assert(*result.at(2) == IntegerTrait::new(12, false), 'result[2] = 12'); + assert(*result.at(3) == IntegerTrait::new(13, false), 'result[3] = 13'); + assert(*result.at(4) == IntegerTrait::new(104, false), 'result[4] = 104'); + assert(*result.at(5) == IntegerTrait::new(105, false), 'result[5] = 105'); + assert(*result.at(6) == IntegerTrait::new(106, false), 'result[6] = 106'); + assert(*result.at(7) == IntegerTrait::new(107, false), 'result[7] = 107'); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result.at(1) == IntegerTrait::new(101, false), 'result[1] = 101'); + assert(*result.at(2) == IntegerTrait::new(12, false), 'result[2] = 12'); + assert(*result.at(3) == IntegerTrait::new(103, false), 'result[3] = 103'); + assert(*result.at(4) == IntegerTrait::new(14, false), 'result[4] = 14'); + assert(*result.at(5) == IntegerTrait::new(105, false), 'result[5] = 105'); + assert(*result.at(6) == IntegerTrait::new(16, false), 'result[6] = 16'); + assert(*result.at(7) == IntegerTrait::new(107, false), 'result[7] = 107'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorSub, Tensor_i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = i32_tensor_2x2x2_helper(); + let tensor_2 = i32_tensor_2x2x2_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(0, false), 'result[1] = 0'); + assert(*result.at(2) == IntegerTrait::new(0, false), 'result[2] = 0'); + assert(*result.at(3) == IntegerTrait::new(0, false), 'result[3] = 0'); + assert(*result.at(4) == IntegerTrait::new(0, false), 'result[4] = 0'); + assert(*result.at(5) == IntegerTrait::new(0, false), 'result[5] = 0'); + assert(*result.at(6) == IntegerTrait::new(0, false), 'result[6] = 0'); + assert(*result.at(7) == IntegerTrait::new(0, false), 'result[7] = 0'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_sub_broadcast() { + let tensor_1 = i32_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result.at(2) == IntegerTrait::new(1, false), 'result[2] = 1'); + assert(*result.at(3) == IntegerTrait::new(2, false), 'result[3] = 2'); + assert(*result.at(4) == IntegerTrait::new(4, false), 'result[4] = 4'); + assert(*result.at(5) == IntegerTrait::new(5, false), 'result[5] = 5'); + assert(*result.at(6) == IntegerTrait::new(5, false), 'result[6] = 5'); + assert(*result.at(7) == IntegerTrait::new(6, false), 'result[7] = 6'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorMul, Tensor_i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = i32_tensor_2x2x2_helper(); + let tensor_2 = i32_tensor_2x2x2_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result.at(3) == IntegerTrait::new(9, false), 'result[3] = 9'); + assert(*result.at(4) == IntegerTrait::new(16, false), 'result[4] = 16'); + assert(*result.at(5) == IntegerTrait::new(25, false), 'result[5] = 25'); + assert(*result.at(6) == IntegerTrait::new(36, false), 'result[6] = 36'); + assert(*result.at(7) == IntegerTrait::new(49, false), 'result[7] = 49'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_mul_broadcast() { + let tensor_1 = i32_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result.at(1) == IntegerTrait::new(10, false), 'result[1] = 10'); + assert(*result.at(2) == IntegerTrait::new(200, false), 'result[2] = 200'); + assert(*result.at(3) == IntegerTrait::new(300, false), 'result[3] = 300'); + assert(*result.at(4) == IntegerTrait::new(40, false), 'result[4] = 40'); + assert(*result.at(5) == IntegerTrait::new(50, false), 'result[5] = 50'); + assert(*result.at(6) == IntegerTrait::new(600, false), 'result[6] = 600'); + assert(*result.at(7) == IntegerTrait::new(700, false), 'result[7] = 700'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::{i32TensorDiv, Tensor_i32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(200, false)); + data.append(IntegerTrait::new(300, false)); + data.append(IntegerTrait::new(400, false)); + data.append(IntegerTrait::new(500, false)); + data.append(IntegerTrait::new(600, false)); + data.append(IntegerTrait::new(700, false)); + data.append(IntegerTrait::new(800, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(1, false), 'result[0] = 1'); + assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result.at(2) == IntegerTrait::new(1, false), 'result[2] = 1'); + assert(*result.at(3) == IntegerTrait::new(1, false), 'result[3] = 1'); + assert(*result.at(4) == IntegerTrait::new(1, false), 'result[4] = 1'); + assert(*result.at(5) == IntegerTrait::new(1, false), 'result[5] = 1'); + assert(*result.at(6) == IntegerTrait::new(1, false), 'result[6] = 1'); + assert(*result.at(7) == IntegerTrait::new(1, false), 'result[7] = 1'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_div_broadcast() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(100, false)); + data.append(IntegerTrait::new(200, false)); + data.append(IntegerTrait::new(300, false)); + data.append(IntegerTrait::new(400, false)); + data.append(IntegerTrait::new(500, false)); + data.append(IntegerTrait::new(600, false)); + data.append(IntegerTrait::new(700, false)); + data.append(IntegerTrait::new(800, false)); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(10, false)); + data.append(IntegerTrait::new(100, false)); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result.at(1) == IntegerTrait::new(20, false), 'result[1] = 20'); + assert(*result.at(2) == IntegerTrait::new(3, false), 'result[2] = 3'); + assert(*result.at(3) == IntegerTrait::new(4, false), 'result[3] = 4'); + assert(*result.at(4) == IntegerTrait::new(50, false), 'result[4] = 50'); + assert(*result.at(5) == IntegerTrait::new(60, false), 'result[5] = 60'); + assert(*result.at(6) == IntegerTrait::new(7, false), 'result[6] = 7'); + assert(*result.at(7) == IntegerTrait::new(8, false), 'result[7] = 8'); + } + } +} diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_u32_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_u32_test.cairo new file mode 100644 index 000000000..b96c6fe02 --- /dev/null +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_u32_test.cairo @@ -0,0 +1,660 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::u32TensorAdd; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = u32_tensor_1x3_helper(); + let tensor_2 = u32_tensor_1x3_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == 0_u32, 'result[0] = 0'); + assert(*result.at(1) == 2_u32, 'result[1] = 2'); + assert(*result.at(2) == 4_u32, 'result[2] = 4'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::u32TensorSub; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = u32_tensor_1x3_helper(); + let tensor_2 = u32_tensor_1x3_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == 0_u32, 'result[0] = 0'); + assert(*result.at(1) == 0_u32, 'result[1] = 0'); + assert(*result.at(2) == 0_u32, 'result[2] = 0'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::u32TensorMul; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = u32_tensor_1x3_helper(); + let tensor_2 = u32_tensor_1x3_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == 0_u32, 'result[0] = 0'); + assert(*result.at(1) == 1_u32, 'result[1] = 1'); + assert(*result.at(2) == 4_u32, 'result[2] = 4'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorDiv, Tensor_u32}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams, ravel_index, unravel_index}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(100); + data.append(200_u32); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == 1, 'result[0] = 1'); + assert(*result.at(1) == 1, 'result[1] = 1'); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorAdd, Tensor_u32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = u32_tensor_2x2_helper(); + let tensor_2 = u32_tensor_2x2_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 2, 'result[1] = 2'); + assert(*result.at(2) == 4, 'result[2] = 4'); + assert(*result.at(3) == 6, 'result[3] = 6'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_add_broadcast() { + let tensor_1 = u32_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == 10, 'result[0] = 10'); + assert(*result.at(1) == 101, 'result[1] = 101'); + assert(*result.at(2) == 12, 'result[2] = 12'); + assert(*result.at(3) == 103, 'result[3] = 103'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == 10, 'result[0] = 10'); + assert(*result.at(1) == 11, 'result[1] = 11'); + assert(*result.at(2) == 102, 'result[2] = 102'); + assert(*result.at(3) == 103, 'result[3] = 103'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorSub, Tensor_u32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = u32_tensor_2x2_helper(); + let tensor_2 = u32_tensor_2x2_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 0, 'result[1] = 0'); + assert(*result.at(2) == 0, 'result[2] = 0'); + assert(*result.at(3) == 0, 'result[3] = 0'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_sub_broadcast() { + let tensor_1 = u32_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 0, 'result[1] = 0'); + assert(*result.at(2) == 2, 'result[2] = 2'); + assert(*result.at(3) == 2, 'result[3] = 2'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 1, 'result[1] = 1'); + assert(*result.at(2) == 1, 'result[2] = 1'); + assert(*result.at(3) == 2, 'result[3] = 2'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorMul, Tensor_u32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = u32_tensor_2x2_helper(); + let tensor_2 = u32_tensor_2x2_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 1, 'result[1] = 1'); + assert(*result.at(2) == 4, 'result[2] = 4'); + assert(*result.at(3) == 9, 'result[3] = 9'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_mul_broadcast() { + let tensor_1 = u32_tensor_2x2_helper(); + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 100, 'result[1] = 100'); + assert(*result.at(2) == 20, 'result[2] = 20'); + assert(*result.at(3) == 300, 'result[3] = 300'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 10, 'result[1] = 10'); + assert(*result.at(2) == 200, 'result[2] = 200'); + assert(*result.at(3) == 300, 'result[3] = 300'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorDiv, Tensor_u32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(100); + data.append(200); + data.append(300); + data.append(400); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == 1, 'result[0] = 1'); + assert(*result.at(1) == 1, 'result[1] = 1'); + assert(*result.at(2) == 1, 'result[2] = 1'); + assert(*result.at(3) == 1, 'result[3] = 1'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_div_broadcast() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(100); + data.append(200); + data.append(300); + data.append(400); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == 10, 'result[0] = 10'); + assert(*result.at(1) == 2, 'result[1] = 2'); + assert(*result.at(2) == 30, 'result[2] = 30'); + assert(*result.at(3) == 4, 'result[3] = 4'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(10_u32); + data.append(100_u32); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == 10, 'result[0] = 10'); + assert(*result.at(1) == 20, 'result[1] = 20'); + assert(*result.at(2) == 3, 'result[2] = 3'); + assert(*result.at(3) == 4, 'result[3] = 4'); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod add { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorAdd, Tensor_u32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_add() { + let tensor_1 = u32_tensor_2x2x2_helper(); + let tensor_2 = u32_tensor_2x2x2_helper(); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 2, 'result[1] = 2'); + assert(*result.at(2) == 4, 'result[2] = 4'); + assert(*result.at(3) == 6, 'result[3] = 6'); + assert(*result.at(4) == 8, 'result[4] = 8'); + assert(*result.at(5) == 10, 'result[5] = 10'); + assert(*result.at(6) == 12, 'result[6] = 12'); + assert(*result.at(7) == 14, 'result[7] = 14'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_add_broadcast() { + let tensor_1 = u32_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == 10, 'result[0] = 10'); + assert(*result.at(1) == 11, 'result[1] = 11'); + assert(*result.at(2) == 102, 'result[2] = 102'); + assert(*result.at(3) == 103, 'result[3] = 103'); + assert(*result.at(4) == 14, 'result[4] = 14'); + assert(*result.at(5) == 15, 'result[5] = 15'); + assert(*result.at(6) == 106, 'result[6] = 106'); + assert(*result.at(7) == 107, 'result[7] = 107'); + + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(1); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == 10, 'result[0] = 10'); + assert(*result.at(1) == 11, 'result[1] = 11'); + assert(*result.at(2) == 12, 'result[2] = 12'); + assert(*result.at(3) == 13, 'result[3] = 13'); + assert(*result.at(4) == 104, 'result[4] = 104'); + assert(*result.at(5) == 105, 'result[5] = 105'); + assert(*result.at(6) == 106, 'result[6] = 106'); + assert(*result.at(7) == 107, 'result[7] = 107'); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(1); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 + tensor_2).data; + + assert(*result.at(0) == 10, 'result[0] = 10'); + assert(*result.at(1) == 101, 'result[1] = 101'); + assert(*result.at(2) == 12, 'result[2] = 12'); + assert(*result.at(3) == 103, 'result[3] = 103'); + assert(*result.at(4) == 14, 'result[4] = 14'); + assert(*result.at(5) == 105, 'result[5] = 105'); + assert(*result.at(6) == 16, 'result[6] = 16'); + assert(*result.at(7) == 107, 'result[7] = 107'); + } + } + + #[cfg(test)] + mod sub { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorSub, Tensor_u32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_sub() { + let tensor_1 = u32_tensor_2x2x2_helper(); + let tensor_2 = u32_tensor_2x2x2_helper(); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 0, 'result[1] = 0'); + assert(*result.at(2) == 0, 'result[2] = 0'); + assert(*result.at(3) == 0, 'result[3] = 0'); + assert(*result.at(4) == 0, 'result[4] = 0'); + assert(*result.at(5) == 0, 'result[5] = 0'); + assert(*result.at(6) == 0, 'result[6] = 0'); + assert(*result.at(7) == 0, 'result[7] = 0'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_sub_broadcast() { + let tensor_1 = u32_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 - tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 1, 'result[1] = 1'); + assert(*result.at(2) == 1, 'result[2] = 1'); + assert(*result.at(3) == 2, 'result[3] = 2'); + assert(*result.at(4) == 4, 'result[4] = 4'); + assert(*result.at(5) == 5, 'result[5] = 5'); + assert(*result.at(6) == 5, 'result[6] = 5'); + assert(*result.at(7) == 6, 'result[7] = 6'); + } + } + + #[cfg(test)] + mod mul { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorMul, Tensor_u32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + #[test] + #[available_gas(20000000)] + fn tensor_mul() { + let tensor_1 = u32_tensor_2x2x2_helper(); + let tensor_2 = u32_tensor_2x2x2_helper(); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 1, 'result[1] = 1'); + assert(*result.at(2) == 4, 'result[2] = 4'); + assert(*result.at(3) == 9, 'result[3] = 9'); + assert(*result.at(4) == 16, 'result[4] = 16'); + assert(*result.at(5) == 25, 'result[5] = 25'); + assert(*result.at(6) == 36, 'result[6] = 36'); + assert(*result.at(7) == 49, 'result[7] = 49'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_mul_broadcast() { + let tensor_1 = u32_tensor_2x2x2_helper(); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 * tensor_2).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 10, 'result[1] = 10'); + assert(*result.at(2) == 200, 'result[2] = 200'); + assert(*result.at(3) == 300, 'result[3] = 300'); + assert(*result.at(4) == 40, 'result[4] = 40'); + assert(*result.at(5) == 50, 'result[5] = 50'); + assert(*result.at(6) == 600, 'result[6] = 600'); + assert(*result.at(7) == 700, 'result[7] = 700'); + } + } + + #[cfg(test)] + mod div { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::{u32TensorDiv, Tensor_u32}; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_div() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(100); + data.append(200); + data.append(300); + data.append(400); + data.append(500); + data.append(600); + data.append(700); + data.append(800); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == 1, 'result[0] = 1'); + assert(*result.at(1) == 1, 'result[1] = 1'); + assert(*result.at(2) == 1, 'result[2] = 1'); + assert(*result.at(3) == 1, 'result[3] = 1'); + assert(*result.at(4) == 1, 'result[4] = 1'); + assert(*result.at(5) == 1, 'result[5] = 1'); + assert(*result.at(6) == 1, 'result[6] = 1'); + assert(*result.at(7) == 1, 'result[7] = 1'); + } + + #[test] + #[available_gas(20000000)] + fn tensor_div_broadcast() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + let mut data = ArrayTrait::new(); + data.append(100); + data.append(200); + data.append(300); + data.append(400); + data.append(500); + data.append(600); + data.append(700); + data.append(800); + let extra = Option::::None(()); + let tensor_1 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let mut sizes = ArrayTrait::new(); + sizes.append(1); + sizes.append(2); + sizes.append(1); + let mut data = ArrayTrait::new(); + data.append(10); + data.append(100); + let extra = Option::::None(()); + let tensor_2 = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = (tensor_1 / tensor_2).data; + + assert(*result.at(0) == 10, 'result[0] = 10'); + assert(*result.at(1) == 20, 'result[1] = 20'); + assert(*result.at(2) == 3, 'result[2] = 3'); + assert(*result.at(3) == 4, 'result[3] = 4'); + assert(*result.at(4) == 50, 'result[4] = 50'); + assert(*result.at(5) == 60, 'result[5] = 60'); + assert(*result.at(6) == 7, 'result[6] = 7'); + assert(*result.at(7) == 8, 'result[7] = 8'); + } + } +} From c3b9eae8b8765cd90b76d7bffc38eaf1674a8557 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 18:15:11 +0300 Subject: [PATCH 039/126] refactor tensor transpose tests --- .../transpose/transpose_fp/fp16x16.cairo | 1 + .../transpose/transpose_fp/fp8x23.cairo | 1 + .../linalg/transpose/transpose_i32.cairo | 1 + .../linalg/transpose/transpose_u32.cairo | 1 + src/tests/helpers/tensor/u32.cairo | 4 +- src/tests/operators/tensor/core.cairo | 3 +- .../operators/tensor/core/transpose.cairo | 3 + .../core/transpose/transpose_fp_test.cairo | 2 + .../transpose_fp16x16_test.cairo | 227 ++++++++++++++++++ .../transpose_fp8x23_test.cairo | 227 ++++++++++++++++++ .../core/transpose/transpose_i32_test.cairo | 223 +++++++++++++++++ .../core/transpose/transpose_u32_test.cairo | 223 +++++++++++++++++ 12 files changed, 913 insertions(+), 3 deletions(-) create mode 100644 src/tests/operators/tensor/core/transpose.cairo create mode 100644 src/tests/operators/tensor/core/transpose/transpose_fp_test.cairo create mode 100644 src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/core/transpose/transpose_i32_test.cairo create mode 100644 src/tests/operators/tensor/core/transpose/transpose_u32_test.cairo diff --git a/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo b/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo index 9a01aae5b..17069aa28 100644 --- a/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo @@ -12,6 +12,7 @@ use orion::utils::check_gas; /// Cf: TensorTrait::transpose docstring fn transpose(self: @Tensor, axes: Span) -> Tensor { + assert((*self.shape).len() > 1, 'cannot transpose a 1D tensor'); assert(axes.len() == (*self.shape).len(), 'shape and axes length unequal'); let output_shape = permutation_output_shape(*self.shape, axes); diff --git a/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo b/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo index b5f8aea4c..a1f0aaa23 100644 --- a/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo @@ -12,6 +12,7 @@ use orion::utils::check_gas; /// Cf: TensorTrait::transpose docstring fn transpose(self: @Tensor, axes: Span) -> Tensor { + assert((*self.shape).len() > 1, 'cannot transpose a 1D tensor'); assert(axes.len() == (*self.shape).len(), 'shape and axes length unequal'); let output_shape = permutation_output_shape(*self.shape, axes); diff --git a/src/operators/tensor/linalg/transpose/transpose_i32.cairo b/src/operators/tensor/linalg/transpose/transpose_i32.cairo index 76d42644f..b080033d9 100644 --- a/src/operators/tensor/linalg/transpose/transpose_i32.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_i32.cairo @@ -11,6 +11,7 @@ use orion::utils::check_gas; /// Cf: TensorTrait::transpose docstring fn transpose(self: @Tensor, axes: Span) -> Tensor { + assert((*self.shape).len() > 1, 'cannot transpose a 1D tensor'); assert(axes.len() == (*self.shape).len(), 'shape and axes length unequal'); let output_shape = permutation_output_shape(*self.shape, axes); diff --git a/src/operators/tensor/linalg/transpose/transpose_u32.cairo b/src/operators/tensor/linalg/transpose/transpose_u32.cairo index e6a777d68..b576651cc 100644 --- a/src/operators/tensor/linalg/transpose/transpose_u32.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_u32.cairo @@ -10,6 +10,7 @@ use orion::utils::check_gas; /// Cf: TensorTrait::transpose docstring fn transpose(self: @Tensor, axes: Span) -> Tensor { + assert((*self.shape).len() > 1, 'cannot transpose a 1D tensor'); assert(axes.len() == (*self.shape).len(), 'shape and axes length unequal'); let output_shape = permutation_output_shape(*self.shape, axes); diff --git a/src/tests/helpers/tensor/u32.cairo b/src/tests/helpers/tensor/u32.cairo index 6cfb79645..dcde6470e 100644 --- a/src/tests/helpers/tensor/u32.cairo +++ b/src/tests/helpers/tensor/u32.cairo @@ -160,8 +160,8 @@ fn u32_tensor_3x2x2_helper() -> Tensor { data.append(7); data.append(8); data.append(9); - data.append(1); - data.append(1); + data.append(10); + data.append(11); let extra = Option::::None(()); diff --git a/src/tests/operators/tensor/core.cairo b/src/tests/operators/tensor/core.cairo index 113893d9c..3886ccfcd 100644 --- a/src/tests/operators/tensor/core.cairo +++ b/src/tests/operators/tensor/core.cairo @@ -1,4 +1,5 @@ mod at; mod stride; mod ravel_index; -mod unravel_index; \ No newline at end of file +mod unravel_index; +mod transpose; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/transpose.cairo b/src/tests/operators/tensor/core/transpose.cairo new file mode 100644 index 000000000..c41e465f9 --- /dev/null +++ b/src/tests/operators/tensor/core/transpose.cairo @@ -0,0 +1,3 @@ +mod transpose_u32_test; +mod transpose_i32_test; +mod transpose_fp_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/transpose/transpose_fp_test.cairo b/src/tests/operators/tensor/core/transpose/transpose_fp_test.cairo new file mode 100644 index 000000000..f0e2bd08f --- /dev/null +++ b/src/tests/operators/tensor/core/transpose/transpose_fp_test.cairo @@ -0,0 +1,2 @@ +mod transpose_fp8x23_test; +mod transpose_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp16x16_test.cairo b/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp16x16_test.cairo new file mode 100644 index 000000000..8b5dd219d --- /dev/null +++ b/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp16x16_test.cairo @@ -0,0 +1,227 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + + #[test] + #[should_panic(expected: ('cannot transpose a 1D tensor', ))] + #[available_gas(2000000)] + fn tensor_transpose() { + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.transpose(axes.span()); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::{ + fp_tensor_2x2_helper, fp_tensor_3x2_helper, fp_tensor_2x3_helper + }; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + + #[test] + #[available_gas(20000000)] + fn tensor_transpose() { + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(0); + + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + + let tensor = fp_tensor_3x2_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(3, false), 'result[4] = 3'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 3, 'shape[1] = 3'); + + let tensor = fp_tensor_2x3_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(3, false), 'result[1] = 3'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.shape.at(0) == 3, 'shape[0] = 3'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp16x16::{ + fp_tensor_2x2x2_helper, fp_tensor_3x2x2_helper, fp_tensor_2x3_helper + }; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16PartialEq}; + + + #[test] + #[available_gas(20000000)] + fn tensor_transpose() { + let tensor = fp_tensor_2x2x2_helper(); + + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(2); + axes.append(0); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(5, false), 'result[3] = 5'); + assert(*result.at(4) == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); + assert(*result.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result.at(6) == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); + assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(2); + axes.append(1); + axes.append(0); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.at(2) == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.at(6) == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); + assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(0); + axes.append(2); + axes.append(1); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + + let tensor = fp_tensor_3x2x2_helper(); + + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(2); + axes.append(0); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(5, false), 'result[4] = 5'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(9, false), 'result[5] = 9'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); + assert(*result.data.at(8) == FixedTrait::new_unscaled(10, false), 'result[8] = 10'); + assert(*result.data.at(9) == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); + assert(*result.data.at(10) == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); + assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(2); + axes.append(1); + axes.append(0); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(6, false), 'result[4] = 6'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(5, false), 'result[7] = 5'); + assert(*result.data.at(8) == FixedTrait::new_unscaled(9, false), 'result[8] = 9'); + assert(*result.data.at(9) == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); + assert(*result.data.at(10) == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); + assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(0); + axes.append(2); + axes.append(1); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result.data.at(8) == FixedTrait::new_unscaled(8, false), 'result[8] = 8'); + assert(*result.data.at(9) == FixedTrait::new_unscaled(10, false), 'result[9] = 10'); + assert(*result.data.at(10) == FixedTrait::new_unscaled(9, false), 'result[10] = 9'); + assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape.at(0) == 3, 'shape[0] = 3'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 2, 'shape[2] = 2'); + } +} diff --git a/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp8x23_test.cairo b/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp8x23_test.cairo new file mode 100644 index 000000000..a160f7020 --- /dev/null +++ b/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp8x23_test.cairo @@ -0,0 +1,227 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + + #[test] + #[should_panic(expected: ('cannot transpose a 1D tensor', ))] + #[available_gas(2000000)] + fn tensor_transpose() { + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + + let tensor = fp_tensor_1x3_helper(); + + let result = tensor.transpose(axes.span()); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::{ + fp_tensor_2x2_helper, fp_tensor_3x2_helper, fp_tensor_2x3_helper + }; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + + #[test] + #[available_gas(20000000)] + fn tensor_transpose() { + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(0); + + let tensor = fp_tensor_2x2_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + + let tensor = fp_tensor_3x2_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(3, false), 'result[4] = 3'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 3, 'shape[1] = 3'); + + let tensor = fp_tensor_2x3_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(3, false), 'result[1] = 3'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.shape.at(0) == 3, 'shape[0] = 3'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::fixed_point::fp8x23::{ + fp_tensor_2x2x2_helper, fp_tensor_3x2x2_helper, fp_tensor_2x3_helper + }; + use orion::numbers::fixed_point::core::FixedTrait; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + + #[test] + #[available_gas(20000000)] + fn tensor_transpose() { + let tensor = fp_tensor_2x2x2_helper(); + + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(2); + axes.append(0); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(5, false), 'result[3] = 5'); + assert(*result.at(4) == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); + assert(*result.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result.at(6) == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); + assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(2); + axes.append(1); + axes.append(0); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.at(2) == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.at(6) == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); + assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(0); + axes.append(2); + axes.append(1); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + + let tensor = fp_tensor_3x2x2_helper(); + + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(2); + axes.append(0); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(5, false), 'result[4] = 5'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(9, false), 'result[5] = 9'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); + assert(*result.data.at(8) == FixedTrait::new_unscaled(10, false), 'result[8] = 10'); + assert(*result.data.at(9) == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); + assert(*result.data.at(10) == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); + assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(2); + axes.append(1); + axes.append(0); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(6, false), 'result[4] = 6'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(5, false), 'result[7] = 5'); + assert(*result.data.at(8) == FixedTrait::new_unscaled(9, false), 'result[8] = 9'); + assert(*result.data.at(9) == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); + assert(*result.data.at(10) == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); + assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(0); + axes.append(2); + axes.append(1); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result.data.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result.data.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result.data.at(8) == FixedTrait::new_unscaled(8, false), 'result[8] = 8'); + assert(*result.data.at(9) == FixedTrait::new_unscaled(10, false), 'result[9] = 10'); + assert(*result.data.at(10) == FixedTrait::new_unscaled(9, false), 'result[10] = 9'); + assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape.at(0) == 3, 'shape[0] = 3'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 2, 'shape[2] = 2'); + } +} diff --git a/src/tests/operators/tensor/core/transpose/transpose_i32_test.cairo b/src/tests/operators/tensor/core/transpose/transpose_i32_test.cairo new file mode 100644 index 000000000..b20436fae --- /dev/null +++ b/src/tests/operators/tensor/core/transpose/transpose_i32_test.cairo @@ -0,0 +1,223 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + + + #[test] + #[should_panic(expected: ('cannot transpose a 1D tensor', ))] + #[available_gas(2000000)] + fn tensor_transpose() { + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + + let tensor = i32_tensor_1x3_helper(); + + let result = tensor.transpose(axes.span()); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::{ + i32_tensor_2x2_helper, i32_tensor_3x2_helper, i32_tensor_2x3_helper + }; + + + #[test] + #[available_gas(20000000)] + fn tensor_transpose() { + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(0); + + let tensor = i32_tensor_2x2_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0).mag == 0, 'result[0] = 0'); + assert(*result.data.at(1).mag == 2, 'result[1] = 2'); + assert(*result.data.at(2).mag == 1, 'result[2] = 1'); + assert(*result.data.at(3).mag == 3, 'result[3] = 3'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + + let tensor = i32_tensor_3x2_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0).mag == 0, 'result[0] = 0'); + assert(*result.data.at(1).mag == 2, 'result[1] = 2'); + assert(*result.data.at(2).mag == 4, 'result[2] = 4'); + assert(*result.data.at(3).mag == 1, 'result[3] = 1'); + assert(*result.data.at(4).mag == 3, 'result[4] = 3'); + assert(*result.data.at(5).mag == 5, 'result[5] = 5'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 3, 'shape[1] = 3'); + + let tensor = i32_tensor_2x3_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0).mag == 0, 'result[0] = 0'); + assert(*result.data.at(1).mag == 3, 'result[1] = 3'); + assert(*result.data.at(2).mag == 1, 'result[2] = 1'); + assert(*result.data.at(3).mag == 4, 'result[3] = 4'); + assert(*result.data.at(4).mag == 2, 'result[4] = 2'); + assert(*result.data.at(5).mag == 5, 'result[5] = 5'); + assert(*result.shape.at(0) == 3, 'shape[0] = 3'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::{ + i32_tensor_2x2x2_helper, i32_tensor_3x2x2_helper, i32_tensor_2x3_helper + }; + + #[test] + #[available_gas(20000000)] + fn tensor_transpose() { + let tensor = i32_tensor_2x2x2_helper(); + + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(2); + axes.append(0); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0).mag == 0, 'result[0] = 0'); + assert(*result.at(1).mag == 4, 'result[1] = 4'); + assert(*result.at(2).mag == 1, 'result[2] = 1'); + assert(*result.at(3).mag == 5, 'result[3] = 5'); + assert(*result.at(4).mag == 2, 'result[4] = 2'); + assert(*result.at(5).mag == 6, 'result[5] = 6'); + assert(*result.at(6).mag == 3, 'result[6] = 3'); + assert(*result.at(7).mag == 7, 'result[7] = 7'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(2); + axes.append(1); + axes.append(0); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0).mag == 0, 'result[0] = 0'); + assert(*result.at(1).mag == 4, 'result[1] = 4'); + assert(*result.at(2).mag == 2, 'result[2] = 2'); + assert(*result.at(3).mag == 6, 'result[3] = 6'); + assert(*result.at(4).mag == 1, 'result[4] = 1'); + assert(*result.at(5).mag == 5, 'result[5] = 5'); + assert(*result.at(6).mag == 3, 'result[6] = 3'); + assert(*result.at(7).mag == 7, 'result[7] = 7'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(0); + axes.append(2); + axes.append(1); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0).mag == 0, 'result[0] = 0'); + assert(*result.at(1).mag == 2, 'result[1] = 2'); + assert(*result.at(2).mag == 1, 'result[2] = 1'); + assert(*result.at(3).mag == 3, 'result[3] = 3'); + assert(*result.at(4).mag == 4, 'result[4] = 4'); + assert(*result.at(5).mag == 6, 'result[5] = 6'); + assert(*result.at(6).mag == 5, 'result[6] = 5'); + assert(*result.at(7).mag == 7, 'result[7] = 7'); + + let tensor = i32_tensor_3x2x2_helper(); + + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(2); + axes.append(0); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0).mag == 0, 'result[0] = 0'); + assert(*result.data.at(1).mag == 4, 'result[1] = 4'); + assert(*result.data.at(2).mag == 8, 'result[2] = 8'); + assert(*result.data.at(3).mag == 1, 'result[3] = 1'); + assert(*result.data.at(4).mag == 5, 'result[4] = 5'); + assert(*result.data.at(5).mag == 9, 'result[5] = 9'); + assert(*result.data.at(6).mag == 2, 'result[6] = 2'); + assert(*result.data.at(7).mag == 6, 'result[7] = 6'); + assert(*result.data.at(8).mag == 10, 'result[8] = 10'); + assert(*result.data.at(9).mag == 3, 'result[9] = 3'); + assert(*result.data.at(10).mag == 7, 'result[10] = 7'); + assert(*result.data.at(11).mag == 11, 'result[11] = 11'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(2); + axes.append(1); + axes.append(0); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0).mag == 0, 'result[0] = 0'); + assert(*result.data.at(1).mag == 4, 'result[1] = 4'); + assert(*result.data.at(2).mag == 8, 'result[2] = 8'); + assert(*result.data.at(3).mag == 2, 'result[3] = 2'); + assert(*result.data.at(4).mag == 6, 'result[4] = 6'); + assert(*result.data.at(5).mag == 10, 'result[5] = 10'); + assert(*result.data.at(6).mag == 1, 'result[6] = 1'); + assert(*result.data.at(7).mag == 5, 'result[7] = 5'); + assert(*result.data.at(8).mag == 9, 'result[8] = 9'); + assert(*result.data.at(9).mag == 3, 'result[9] = 3'); + assert(*result.data.at(10).mag == 7, 'result[10] = 7'); + assert(*result.data.at(11).mag == 11, 'result[11] = 11'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(0); + axes.append(2); + axes.append(1); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0).mag == 0, 'result[0] = 0'); + assert(*result.data.at(1).mag == 2, 'result[1] = 2'); + assert(*result.data.at(2).mag == 1, 'result[2] = 1'); + assert(*result.data.at(3).mag == 3, 'result[3] = 3'); + assert(*result.data.at(4).mag == 4, 'result[4] = 4'); + assert(*result.data.at(5).mag == 6, 'result[5] = 6'); + assert(*result.data.at(6).mag == 5, 'result[6] = 5'); + assert(*result.data.at(7).mag == 7, 'result[7] = 7'); + assert(*result.data.at(8).mag == 8, 'result[8] = 8'); + assert(*result.data.at(9).mag == 10, 'result[9] = 10'); + assert(*result.data.at(10).mag == 9, 'result[10] = 9'); + assert(*result.data.at(11).mag == 11, 'result[11] = 11'); + assert(*result.shape.at(0) == 3, 'shape[0] = 3'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 2, 'shape[2] = 2'); + } +} diff --git a/src/tests/operators/tensor/core/transpose/transpose_u32_test.cairo b/src/tests/operators/tensor/core/transpose/transpose_u32_test.cairo new file mode 100644 index 000000000..902c0f5c0 --- /dev/null +++ b/src/tests/operators/tensor/core/transpose/transpose_u32_test.cairo @@ -0,0 +1,223 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + + #[test] + #[should_panic(expected: ('cannot transpose a 1D tensor', ))] + #[available_gas(2000000)] + fn tensor_transpose() { + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + + let tensor = u32_tensor_1x3_helper(); + + let result = tensor.transpose(axes.span()); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::{ + u32_tensor_2x2_helper, u32_tensor_3x2_helper, u32_tensor_2x3_helper + }; + + + #[test] + #[available_gas(20000000)] + fn tensor_transpose() { + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(0); + + let tensor = u32_tensor_2x2_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 2, 'result[1] = 2'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); + assert(*result.data.at(3) == 3, 'result[3] = 3'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + + let tensor = u32_tensor_3x2_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 2, 'result[1] = 2'); + assert(*result.data.at(2) == 4, 'result[2] = 4'); + assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data.at(4) == 3, 'result[4] = 3'); + assert(*result.data.at(5) == 5, 'result[5] = 5'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 3, 'shape[1] = 3'); + + let tensor = u32_tensor_2x3_helper(); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 3, 'result[1] = 3'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); + assert(*result.data.at(3) == 4, 'result[3] = 4'); + assert(*result.data.at(4) == 2, 'result[4] = 2'); + assert(*result.data.at(5) == 5, 'result[5] = 5'); + assert(*result.shape.at(0) == 3, 'shape[0] = 3'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::{ + u32_tensor_2x2x2_helper, u32_tensor_3x2x2_helper, u32_tensor_2x3_helper + }; + + #[test] + #[available_gas(20000000)] + fn tensor_transpose() { + let tensor = u32_tensor_2x2x2_helper(); + + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(2); + axes.append(0); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 4, 'result[1] = 4'); + assert(*result.at(2) == 1, 'result[2] = 1'); + assert(*result.at(3) == 5, 'result[3] = 5'); + assert(*result.at(4) == 2, 'result[4] = 2'); + assert(*result.at(5) == 6, 'result[5] = 6'); + assert(*result.at(6) == 3, 'result[6] = 3'); + assert(*result.at(7) == 7, 'result[7] = 7'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(2); + axes.append(1); + axes.append(0); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 4, 'result[1] = 4'); + assert(*result.at(2) == 2, 'result[2] = 2'); + assert(*result.at(3) == 6, 'result[3] = 6'); + assert(*result.at(4) == 1, 'result[4] = 1'); + assert(*result.at(5) == 5, 'result[5] = 5'); + assert(*result.at(6) == 3, 'result[6] = 3'); + assert(*result.at(7) == 7, 'result[7] = 7'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(0); + axes.append(2); + axes.append(1); + + let result = tensor.transpose(axes.span()).data; + + assert(*result.at(0) == 0, 'result[0] = 0'); + assert(*result.at(1) == 2, 'result[1] = 2'); + assert(*result.at(2) == 1, 'result[2] = 1'); + assert(*result.at(3) == 3, 'result[3] = 3'); + assert(*result.at(4) == 4, 'result[4] = 4'); + assert(*result.at(5) == 6, 'result[5] = 6'); + assert(*result.at(6) == 5, 'result[6] = 5'); + assert(*result.at(7) == 7, 'result[7] = 7'); + + let tensor = u32_tensor_3x2x2_helper(); + + let mut axes: Array = ArrayTrait::new(); + axes.append(1); + axes.append(2); + axes.append(0); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 4, 'result[1] = 4'); + assert(*result.data.at(2) == 8, 'result[2] = 8'); + assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data.at(4) == 5, 'result[4] = 5'); + assert(*result.data.at(5) == 9, 'result[5] = 9'); + assert(*result.data.at(6) == 2, 'result[6] = 2'); + assert(*result.data.at(7) == 6, 'result[7] = 6'); + assert(*result.data.at(8) == 10, 'result[8] = 10'); + assert(*result.data.at(9) == 3, 'result[9] = 3'); + assert(*result.data.at(10) == 7, 'result[10] = 7'); + assert(*result.data.at(11) == 11, 'result[11] = 11'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(2); + axes.append(1); + axes.append(0); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 4, 'result[1] = 4'); + assert(*result.data.at(2) == 8, 'result[2] = 8'); + assert(*result.data.at(3) == 2, 'result[3] = 2'); + assert(*result.data.at(4) == 6, 'result[4] = 6'); + assert(*result.data.at(5) == 10, 'result[5] = 10'); + assert(*result.data.at(6) == 1, 'result[6] = 1'); + assert(*result.data.at(7) == 5, 'result[7] = 5'); + assert(*result.data.at(8) == 9, 'result[8] = 9'); + assert(*result.data.at(9) == 3, 'result[9] = 3'); + assert(*result.data.at(10) == 7, 'result[10] = 7'); + assert(*result.data.at(11) == 11, 'result[11] = 11'); + assert(*result.shape.at(0) == 2, 'shape[0] = 2'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + + let mut axes: Array = ArrayTrait::new(); + axes.append(0); + axes.append(2); + axes.append(1); + + let result = tensor.transpose(axes.span()); + + assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data.at(1) == 2, 'result[1] = 2'); + assert(*result.data.at(2) == 1, 'result[2] = 1'); + assert(*result.data.at(3) == 3, 'result[3] = 3'); + assert(*result.data.at(4) == 4, 'result[4] = 4'); + assert(*result.data.at(5) == 6, 'result[5] = 6'); + assert(*result.data.at(6) == 5, 'result[6] = 5'); + assert(*result.data.at(7) == 7, 'result[7] = 7'); + assert(*result.data.at(8) == 8, 'result[8] = 8'); + assert(*result.data.at(9) == 10, 'result[9] = 10'); + assert(*result.data.at(10) == 9, 'result[10] = 9'); + assert(*result.data.at(11) == 11, 'result[11] = 11'); + assert(*result.shape.at(0) == 3, 'shape[0] = 3'); + assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.shape.at(2) == 2, 'shape[2] = 2'); + } +} From 8cefc76029e24b667e202da0e36baf1557068c90 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 21 Jun 2023 18:21:54 +0300 Subject: [PATCH 040/126] Update CHANGELOG.md --- docs/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e3956cf25..1e2af543f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] - 2023-06-21 + +### Changed +- Refactor tensor tests to cover n-dimensions + ## [Unreleased] - 2023-06-20 ### Changed From 45823a64c48bd91f920bcae1b1ee97c080f400b1 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 09:16:41 +0300 Subject: [PATCH 041/126] refactor leaky_relu tests --- .../leaky_relu/leaky_relu_i32_test.cairo | 387 ++++++++++++++-- .../leaky_relu/leaky_relu_u32_test.cairo | 416 +++++++++++++++--- 2 files changed, 703 insertions(+), 100 deletions(-) diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo index 8eb08aa33..14c395c09 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo @@ -1,49 +1,342 @@ -use core::option::OptionTrait; -use array::ArrayTrait; -use array::SpanTrait; -use traits::Into; -use core::integer::NumericLiteral; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32::NN_i32; -use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE, FP8x23Into}; - -#[test] -#[available_gas(2000000)] -fn leaky_relu_i32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(3); - - let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(1, false); - let val_2 = IntegerTrait::new(2, false); - let val_3 = IntegerTrait::new(1, true); - let val_4 = IntegerTrait::new(2, true); - let val_5 = IntegerTrait::new(0, false); - let val_6 = IntegerTrait::new(0, false); - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - data.append(val_5); - data.append(val_6); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); - let alpha = FixedTrait::new(838861, false); // 0.1 - let threshold = IntegerTrait::new(0, false); - - let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - - assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 - assert((*result.data.at(3)).into() == -1677722, 'result[3] == - 1677722'); // 2 * 0.1 = - 0.2 - assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE, FP8x23Into}; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(6); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(0, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(838861, false); // 0.1 + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 + assert( + (*result.data.at(3)).into() == -1677722, 'result[3] == - 1677722' + ); // 2 * 0.1 = - 0.2 + assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, ONE, FP16x16Into + }; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(6); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(0, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(6554, false); // 0.1 + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + assert((*result.data.at(0)).into() == 65536, 'result[0] == 65536'); // 1 + assert( + (*result.data.at(3)).into() == -13108, 'result[3] == - 13108' + ); // 2 * 0.1 = - 0.2 + assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + } + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE, FP8x23Into}; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(3); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(0, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(838861, false); // 0.1 + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 + assert( + (*result.data.at(3)).into() == -1677722, 'result[3] == - 1677722' + ); // 2 * 0.1 = - 0.2 + assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, ONE, FP16x16Into + }; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(3); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(0, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(6554, false); // 0.1 + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + assert((*result.data.at(0)).into() == 65536, 'result[0] == 65536'); // 1 + assert( + (*result.data.at(3)).into() == -13108, 'result[3] == - 13108' + ); // 2 * 0.1 = - 0.2 + assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, ONE, FP8x23Into}; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(0, false); + let val_7 = IntegerTrait::new(0, false); + let val_8 = IntegerTrait::new(0, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(838861, false); // 0.1 + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 + assert( + (*result.data.at(3)).into() == -1677722, 'result[3] == - 1677722' + ); // 2 * 0.1 = - 0.2 + assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, ONE, FP16x16Into + }; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(0, false); + let val_7 = IntegerTrait::new(0, false); + let val_8 = IntegerTrait::new(0, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(6554, false); // 0.1 + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + assert((*result.data.at(0)).into() == 65536, 'result[0] == 65536'); // 1 + assert( + (*result.data.at(3)).into() == -13108, 'result[3] == - 13108' + ); // 2 * 0.1 = - 0.2 + assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + } + } } diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo index e9ba81712..95f2b655a 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo @@ -1,55 +1,365 @@ -use core::option::OptionTrait; -use core::traits::Into; -use array::ArrayTrait; -use array::SpanTrait; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32::NN_u32; -use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; - -#[test] -#[available_gas(2000000)] -fn leaky_relu_u32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(3); - - let mut data = ArrayTrait::::new(); - let val_1 = 4; - let val_2 = 3; - let val_3 = 2; - let val_4 = 1; - let val_5 = 0; - let val_6 = 0; - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - data.append(val_5); - data.append(val_6); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); - let alpha = FixedTrait::new(838861, false); // 0.1 - let threshold = 3; - let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - - let data = *result.data.at(0); - assert(data == FixedTrait::new(33554432, false), 'result[0] == 33554432'); // 4 - - let data = *result.data.at(1); - assert(data == FixedTrait::new(25165824, false), 'result[1] == 25165824'); // 3 - - let data = *result.data.at(3); - assert(data == FixedTrait::new(838861, false), 'result[3] == 838861'); // 0.1 - - let data =*result.data.at(5); - assert(data == FixedTrait::new(0, false), 'result[5] == 0'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(6); + + let mut data = ArrayTrait::::new(); + let val_1 = 4; + let val_2 = 3; + let val_3 = 2; + let val_4 = 1; + let val_5 = 0; + let val_6 = 0; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(838861, false); // 0.1 + let threshold = 3; + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(33554432, false), 'result[0] == 33554432'); // 4 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(25165824, false), 'result[1] == 25165824'); // 3 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(838861, false), 'result[3] == 838861'); // 0.1 + + let data = *result.data.at(5); + assert(data == FixedTrait::new(0, false), 'result[5] == 0'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16PartialEq + }; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(6); + + let mut data = ArrayTrait::::new(); + let val_1 = 4; + let val_2 = 3; + let val_3 = 2; + let val_4 = 1; + let val_5 = 0; + let val_6 = 0; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(6554, false); // 0.1 + let threshold = 3; + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(262144, false), 'result[0] == 262144'); // 4 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(196608, false), 'result[1] == 196608'); // 3 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(6554, false), 'result[3] == 6554'); // 0.1 + + let data = *result.data.at(5); + assert(data == FixedTrait::new(0, false), 'result[5] == 0'); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(3); + + let mut data = ArrayTrait::::new(); + let val_1 = 4; + let val_2 = 3; + let val_3 = 2; + let val_4 = 1; + let val_5 = 0; + let val_6 = 0; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(838861, false); // 0.1 + let threshold = 3; + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(33554432, false), 'result[0] == 33554432'); // 4 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(25165824, false), 'result[1] == 25165824'); // 3 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(838861, false), 'result[3] == 838861'); // 0.1 + + let data = *result.data.at(5); + assert(data == FixedTrait::new(0, false), 'result[5] == 0'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16PartialEq + }; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(3); + + let mut data = ArrayTrait::::new(); + let val_1 = 4; + let val_2 = 3; + let val_3 = 2; + let val_4 = 1; + let val_5 = 0; + let val_6 = 0; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(6554, false); // 0.1 + let threshold = 3; + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(262144, false), 'result[0] == 262144'); // 4 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(196608, false), 'result[1] == 196608'); // 3 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(6554, false), 'result[3] == 6554'); // 0.1 + + let data = *result.data.at(5); + assert(data == FixedTrait::new(0, false), 'result[5] == 0'); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 4; + let val_2 = 3; + let val_3 = 2; + let val_4 = 1; + let val_5 = 0; + let val_6 = 0; + let val_7 = 0; + let val_8 = 0; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(838861, false); // 0.1 + let threshold = 3; + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(33554432, false), 'result[0] == 33554432'); // 4 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(25165824, false), 'result[1] == 25165824'); // 3 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(838861, false), 'result[3] == 838861'); // 0.1 + + let data = *result.data.at(5); + assert(data == FixedTrait::new(0, false), 'result[5] == 0'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16PartialEq + }; + + #[test] + #[available_gas(2000000)] + fn leaky_relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 4; + let val_2 = 3; + let val_3 = 2; + let val_4 = 1; + let val_5 = 0; + let val_6 = 0; + let val_7 = 0; + let val_8 = 0; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let alpha = FixedTrait::new(6554, false); // 0.1 + let threshold = 3; + let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(262144, false), 'result[0] == 262144'); // 4 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(196608, false), 'result[1] == 196608'); // 3 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(6554, false), 'result[3] == 6554'); // 0.1 + + let data = *result.data.at(5); + assert(data == FixedTrait::new(0, false), 'result[5] == 0'); + } + } } From 08dba46facfb0e3bef3a91285fff0cec6acf84bd Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 11:40:27 +0300 Subject: [PATCH 042/126] refactor logsoftmax tests --- .../operators/nn/functional/logsoftmax.cairo | 3 +- .../logsoftmax/logsoftmax_i32_test.cairo | 300 ++++++++++++++++++ .../logsoftmax/logsoftmax_test.cairo | 32 -- .../logsoftmax/logsoftmax_u32_test.cairo | 300 ++++++++++++++++++ 4 files changed, 602 insertions(+), 33 deletions(-) create mode 100644 src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo delete mode 100644 src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo create mode 100644 src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo diff --git a/src/tests/operators/nn/functional/logsoftmax.cairo b/src/tests/operators/nn/functional/logsoftmax.cairo index 342aed7a4..542746d2d 100644 --- a/src/tests/operators/nn/functional/logsoftmax.cairo +++ b/src/tests/operators/nn/functional/logsoftmax.cairo @@ -1 +1,2 @@ -mod logsoftmax_test; \ No newline at end of file +mod logsoftmax_i32_test; +mod logsoftmax_u32_test; \ No newline at end of file diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo new file mode 100644 index 000000000..5dc140dbf --- /dev/null +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo @@ -0,0 +1,300 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(20000000)] + fn logsoftmax() { + let tensor = i32_tensor_1x3_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -20196463, 'result[0] = -2.40760596'); + assert((*result[1]).into() == -11807856, 'result[1] = -1.40760596'); + assert((*result[2]).into() == -3419249, 'result[2] = -0.40760596'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = i32_tensor_1x3_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 1); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(20000000)] + fn logsoftmax() { + let tensor = i32_tensor_1x3_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -157788, 'result[0] = -2.40760596'); + assert((*result[1]).into() == -92250, 'result[1] = -1.40760596'); + assert((*result[2]).into() == -26710, 'result[2] = -0.40760596'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = i32_tensor_1x3_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 1); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(20000000)] + fn logsoftmax() { + let tensor = i32_tensor_2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -17841970, 'result[0] = -2.12693'); + assert((*result[1]).into() == -17841970, 'result[1] = -2.12695'); + assert((*result[2]).into() == -1064751, 'result[2] = -0.12692'); + assert((*result[3]).into() == -1064751, 'result[3] = -0.12692'); + + let mut result = NNTrait::logsoftmax(@tensor, 1).data; + + assert((*result.at(0)).into() == -11016451, 'result[0] = -1.3134'); + assert((*result.at(1)).into() == -2627827, 'result[1] = -0.3132'); + assert((*result.at(2)).into() == -11016460, 'result[2] = -1.3134'); + assert((*result.at(3)).into() == -2627829, 'result[3] = -0.3132'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = i32_tensor_2x2_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 2); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(20000000)] + fn logsoftmax() { + let tensor = i32_tensor_2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -139390, 'result[0] = -2.12693'); + assert((*result[1]).into() == -139390, 'result[1] = -2.12695'); + assert((*result[2]).into() == -8317, 'result[2] = -0.12692'); + assert((*result[3]).into() == -8317, 'result[3] = -0.12692'); + + let mut result = NNTrait::logsoftmax(@tensor, 1).data; + + assert((*result.at(0)).into() == -86024, 'result[0] = -1.3134'); + assert((*result.at(1)).into() == -20523, 'result[1] = -0.3132'); + assert((*result.at(2)).into() == -86024, 'result[2] = -1.3134'); + assert((*result.at(3)).into() == -20523, 'result[3] = -0.3132'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = i32_tensor_2x2_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 2); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(200000000)] + fn logsoftmax() { + let tensor = i32_tensor_2x2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -33706687, 'result[0] = -4.01814993'); + assert((*result[1]).into() == -33706687, 'result[1] = -4.01814993'); + assert((*result[2]).into() == -33706687, 'result[2] = -4.01814993'); + assert((*result[3]).into() == -33706687, 'result[3] = -4.01814993'); + assert((*result[4]).into() == -152253, 'result[4] = -0.01814993'); + assert((*result[5]).into() == -152253, 'result[5] = -0.01814993'); + assert((*result[6]).into() == -152253, 'result[6] = -0.01814993'); + assert((*result[7]).into() == -152253, 'result[7] = -0.01814993'); + + let mut result = NNTrait::logsoftmax(@tensor, 1).data; + + assert((*result[0]).into() == -17841970, 'result[0] = -2.12692801'); + assert((*result[1]).into() == -17841970, 'result[1] = -2.12692801'); + assert((*result[2]).into() == -1064751, 'result[2] = -0.12692801'); + assert((*result[3]).into() == -1064751, 'result[3] = -0.12692801'); + assert((*result[4]).into() == -17841970, 'result[4] = -2.12692801'); + assert((*result[5]).into() == -17841970, 'result[5] = -2.12692801'); + assert((*result[6]).into() == -1064751, 'result[6] = -0.12692801'); + assert((*result[7]).into() == -1064751, 'result[7] = -0.12692801'); + + let mut result = NNTrait::logsoftmax(@tensor, 2).data; + + assert((*result[0]).into() == -11016451, 'result[0] = -1.31326169'); + assert((*result[1]).into() == -2627827, 'result[1] = -0.31326169'); + assert((*result[2]).into() == -11016460, 'result[2] = -1.31326169'); + assert((*result[3]).into() == -2627829, 'result[3] = -0.31326169'); + assert((*result[4]).into() == -11016451, 'result[4] = -1.31326169'); + assert((*result[5]).into() == -2627827, 'result[5] = -0.31326169'); + assert((*result[6]).into() == -11016451, 'result[6] = -1.31326169'); + assert((*result[7]).into() == -2627827, 'result[7] = -0.31326169'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = i32_tensor_2x2x2_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 3); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(200000000)] + fn logsoftmax() { + let tensor = i32_tensor_2x2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -263347, 'result[0] = -4.01814993'); + assert((*result[1]).into() == -263347, 'result[1] = -4.01814993'); + assert((*result[2]).into() == -263347, 'result[2] = -4.01814993'); + assert((*result[3]).into() == -263347, 'result[3] = -4.01814993'); + assert((*result[4]).into() == -1188, 'result[4] = -0.01814993'); + assert((*result[5]).into() == -1188, 'result[5] = -0.01814993'); + assert((*result[6]).into() == -1188, 'result[6] = -0.01814993'); + assert((*result[7]).into() == -1188, 'result[7] = -0.01814993'); + + let mut result = NNTrait::logsoftmax(@tensor, 1).data; + + assert((*result[0]).into() == -139390, 'result[0] = -2.12692801'); + assert((*result[1]).into() == -139390, 'result[1] = -2.12692801'); + assert((*result[2]).into() == -8317, 'result[2] = -0.12692801'); + assert((*result[3]).into() == -8317, 'result[3] = -0.12692801'); + assert((*result[4]).into() == -139390, 'result[4] = -2.12692801'); + assert((*result[5]).into() == -139390, 'result[5] = -2.12692801'); + assert((*result[6]).into() == -8317, 'result[6] = -0.12692801'); + assert((*result[7]).into() == -8317, 'result[7] = -0.12692801'); + + let mut result = NNTrait::logsoftmax(@tensor, 2).data; + + assert((*result[0]).into() == -86024, 'result[0] = -1.31326169'); + assert((*result[1]).into() == -20523, 'result[1] = -0.31326169'); + assert((*result[2]).into() == -86024, 'result[2] = -1.31326169'); + assert((*result[3]).into() == -20523, 'result[3] = -0.31326169'); + assert((*result[4]).into() == -86024, 'result[4] = -1.31326169'); + assert((*result[5]).into() == -20523, 'result[5] = -0.31326169'); + assert((*result[6]).into() == -86024, 'result[6] = -1.31326169'); + assert((*result[7]).into() == -20523, 'result[7] = -0.31326169'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = i32_tensor_2x2x2_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 3); + } + } +} diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo deleted file mode 100644 index abf545b34..000000000 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_test.cairo +++ /dev/null @@ -1,32 +0,0 @@ -use array::SpanTrait; -use traits::Into; - -use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::fixed_point::core::FixedImpl; -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32::NN_i32; - -#[test] -#[available_gas(20000000)] -fn logsoftmax_test() { - let tensor = i32_tensor_2x2_helper(); - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); - - let mut result = NNTrait::logsoftmax(@tensor, 0).data; - - assert((*result[0]).into() == -17841970, 'result[0] = -2.12693'); - assert((*result[1]).into() == -17841970, 'result[1] = -2.12695'); - assert((*result[2]).into() == -1064751, 'result[2] = -0.12692'); - assert((*result[3]).into() == -1064751, 'result[3] = -0.12692'); - - let mut result = NNTrait::logsoftmax(@tensor, 1).data; - - assert((*result.at(0)).into() == -11016451, 'result[0] = -1.3134'); - assert((*result.at(1)).into() == -2627827, 'result[1] = -0.3132'); - assert((*result.at(2)).into() == -11016460, 'result[2] = -1.3134'); - assert((*result.at(3)).into() == -2627829, 'result[3] = -0.3132'); -} diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo new file mode 100644 index 000000000..ced70e521 --- /dev/null +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo @@ -0,0 +1,300 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(20000000)] + fn logsoftmax() { + let tensor = u32_tensor_1x3_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -20196463, 'result[0] = -2.40760596'); + assert((*result[1]).into() == -11807856, 'result[1] = -1.40760596'); + assert((*result[2]).into() == -3419249, 'result[2] = -0.40760596'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = u32_tensor_1x3_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 1); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(20000000)] + fn logsoftmax() { + let tensor = u32_tensor_1x3_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -157788, 'result[0] = -2.40760596'); + assert((*result[1]).into() == -92250, 'result[1] = -1.40760596'); + assert((*result[2]).into() == -26710, 'result[2] = -0.40760596'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = u32_tensor_1x3_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 1); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(20000000)] + fn logsoftmax() { + let tensor = u32_tensor_2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -17841970, 'result[0] = -2.12693'); + assert((*result[1]).into() == -17841970, 'result[1] = -2.12695'); + assert((*result[2]).into() == -1064751, 'result[2] = -0.12692'); + assert((*result[3]).into() == -1064751, 'result[3] = -0.12692'); + + let mut result = NNTrait::logsoftmax(@tensor, 1).data; + + assert((*result.at(0)).into() == -11016451, 'result[0] = -1.3134'); + assert((*result.at(1)).into() == -2627827, 'result[1] = -0.3132'); + assert((*result.at(2)).into() == -11016460, 'result[2] = -1.3134'); + assert((*result.at(3)).into() == -2627829, 'result[3] = -0.3132'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = u32_tensor_2x2_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 2); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(20000000)] + fn logsoftmax() { + let tensor = u32_tensor_2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -139390, 'result[0] = -2.12693'); + assert((*result[1]).into() == -139390, 'result[1] = -2.12695'); + assert((*result[2]).into() == -8317, 'result[2] = -0.12692'); + assert((*result[3]).into() == -8317, 'result[3] = -0.12692'); + + let mut result = NNTrait::logsoftmax(@tensor, 1).data; + + assert((*result.at(0)).into() == -86024, 'result[0] = -1.3134'); + assert((*result.at(1)).into() == -20523, 'result[1] = -0.3132'); + assert((*result.at(2)).into() == -86024, 'result[2] = -1.3134'); + assert((*result.at(3)).into() == -20523, 'result[3] = -0.3132'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = u32_tensor_2x2_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 2); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(200000000)] + fn logsoftmax() { + let tensor = u32_tensor_2x2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -33706687, 'result[0] = -4.01814993'); + assert((*result[1]).into() == -33706687, 'result[1] = -4.01814993'); + assert((*result[2]).into() == -33706687, 'result[2] = -4.01814993'); + assert((*result[3]).into() == -33706687, 'result[3] = -4.01814993'); + assert((*result[4]).into() == -152253, 'result[4] = -0.01814993'); + assert((*result[5]).into() == -152253, 'result[5] = -0.01814993'); + assert((*result[6]).into() == -152253, 'result[6] = -0.01814993'); + assert((*result[7]).into() == -152253, 'result[7] = -0.01814993'); + + let mut result = NNTrait::logsoftmax(@tensor, 1).data; + + assert((*result[0]).into() == -17841970, 'result[0] = -2.12692801'); + assert((*result[1]).into() == -17841970, 'result[1] = -2.12692801'); + assert((*result[2]).into() == -1064751, 'result[2] = -0.12692801'); + assert((*result[3]).into() == -1064751, 'result[3] = -0.12692801'); + assert((*result[4]).into() == -17841970, 'result[4] = -2.12692801'); + assert((*result[5]).into() == -17841970, 'result[5] = -2.12692801'); + assert((*result[6]).into() == -1064751, 'result[6] = -0.12692801'); + assert((*result[7]).into() == -1064751, 'result[7] = -0.12692801'); + + let mut result = NNTrait::logsoftmax(@tensor, 2).data; + + assert((*result[0]).into() == -11016451, 'result[0] = -1.31326169'); + assert((*result[1]).into() == -2627827, 'result[1] = -0.31326169'); + assert((*result[2]).into() == -11016460, 'result[2] = -1.31326169'); + assert((*result[3]).into() == -2627829, 'result[3] = -0.31326169'); + assert((*result[4]).into() == -11016451, 'result[4] = -1.31326169'); + assert((*result[5]).into() == -2627827, 'result[5] = -0.31326169'); + assert((*result[6]).into() == -11016451, 'result[6] = -1.31326169'); + assert((*result[7]).into() == -2627827, 'result[7] = -0.31326169'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = u32_tensor_2x2x2_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 3); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(200000000)] + fn logsoftmax() { + let tensor = u32_tensor_2x2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::logsoftmax(@tensor, 0).data; + + assert((*result[0]).into() == -263347, 'result[0] = -4.01814993'); + assert((*result[1]).into() == -263347, 'result[1] = -4.01814993'); + assert((*result[2]).into() == -263347, 'result[2] = -4.01814993'); + assert((*result[3]).into() == -263347, 'result[3] = -4.01814993'); + assert((*result[4]).into() == -1188, 'result[4] = -0.01814993'); + assert((*result[5]).into() == -1188, 'result[5] = -0.01814993'); + assert((*result[6]).into() == -1188, 'result[6] = -0.01814993'); + assert((*result[7]).into() == -1188, 'result[7] = -0.01814993'); + + let mut result = NNTrait::logsoftmax(@tensor, 1).data; + + assert((*result[0]).into() == -139390, 'result[0] = -2.12692801'); + assert((*result[1]).into() == -139390, 'result[1] = -2.12692801'); + assert((*result[2]).into() == -8317, 'result[2] = -0.12692801'); + assert((*result[3]).into() == -8317, 'result[3] = -0.12692801'); + assert((*result[4]).into() == -139390, 'result[4] = -2.12692801'); + assert((*result[5]).into() == -139390, 'result[5] = -2.12692801'); + assert((*result[6]).into() == -8317, 'result[6] = -0.12692801'); + assert((*result[7]).into() == -8317, 'result[7] = -0.12692801'); + + let mut result = NNTrait::logsoftmax(@tensor, 2).data; + + assert((*result[0]).into() == -86024, 'result[0] = -1.31326169'); + assert((*result[1]).into() == -20523, 'result[1] = -0.31326169'); + assert((*result[2]).into() == -86024, 'result[2] = -1.31326169'); + assert((*result[3]).into() == -20523, 'result[3] = -0.31326169'); + assert((*result[4]).into() == -86024, 'result[4] = -1.31326169'); + assert((*result[5]).into() == -20523, 'result[5] = -0.31326169'); + assert((*result[6]).into() == -86024, 'result[6] = -1.31326169'); + assert((*result[7]).into() == -20523, 'result[7] = -0.31326169'); + } + + #[test] + #[should_panic(expected: ('axis out of dimensions', ))] + #[available_gas(20000000)] + fn wrong_axis() { + let tensor = u32_tensor_2x2x2_helper(); + let mut result = NNTrait::logsoftmax(@tensor, 3); + } + } +} From 834d7a972ba0ef5ec60ebf267649056744f98912 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 13:21:53 +0300 Subject: [PATCH 043/126] refactor relu tests --- .../nn/functional/relu/relu_i32_test.cairo | 180 +++++++++++---- .../nn/functional/relu/relu_u32_test.cairo | 215 ++++++++++++++---- 2 files changed, 313 insertions(+), 82 deletions(-) diff --git a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo index 17f317d48..7fb45f98d 100644 --- a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo @@ -1,39 +1,143 @@ -use array::ArrayTrait; -use array::SpanTrait; -use traits::Into; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32::NN_i32; - -#[test] -#[available_gas(2000000)] -fn relu_i32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(2); - - let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(1, false); - let val_2 = IntegerTrait::new(2, false); - let val_3 = IntegerTrait::new(1, true); - let val_4 = IntegerTrait::new(2, true); - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - - let extra = Option::::None(()); - - let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); - let threshold = IntegerTrait::new(0, false); - - let mut result = NNTrait::relu(@tensor, threshold); - - let data_0 = *result.data.at(0); - assert((*result.data.at(0)).into() == 1, 'result[0] == 1'); - assert((*result.data.at(3)).into() == 0, 'result[3] == 0'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(2000000)] + fn relu() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = Option::::None(()); + + let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::relu(@tensor, threshold); + + let data_0 = *result.data.at(0); + assert((*result.data.at(0)).into() == 1, 'result[0] == 1'); + assert((*result.data.at(3)).into() == 0, 'result[3] == 0'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(2000000)] + fn relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = Option::::None(()); + + let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::relu(@tensor, threshold); + + let data_0 = *result.data.at(0); + assert((*result.data.at(0)).into() == 1, 'result[0] == 1'); + assert((*result.data.at(3)).into() == 0, 'result[3] == 0'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(2000000)] + fn relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(1, false); + let val_2 = IntegerTrait::new(2, false); + let val_3 = IntegerTrait::new(1, true); + let val_4 = IntegerTrait::new(2, true); + let val_5 = IntegerTrait::new(1, false); + let val_6 = IntegerTrait::new(2, false); + let val_7 = IntegerTrait::new(1, true); + let val_8 = IntegerTrait::new(2, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = Option::::None(()); + + let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); + let threshold = IntegerTrait::new(0, false); + + let mut result = NNTrait::relu(@tensor, threshold); + + let data_0 = *result.data.at(0); + assert((*result.data.at(0)).into() == 1, 'result[0] == 1'); + assert((*result.data.at(3)).into() == 0, 'result[3] == 0'); + assert((*result.data.at(5)).into() == 2, 'result[6] == 2'); + } } diff --git a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo index 9cd4d5274..1fd1a488c 100644 --- a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo @@ -1,45 +1,172 @@ -use array::ArrayTrait; -use array::SpanTrait; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32::NN_u32; - -#[test] -#[available_gas(2000000)] -fn relu_u32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(2); - - let mut data = ArrayTrait::::new(); - let val_1 = 1; - let val_2 = 2; - let val_3 = 3; - let val_4 = 4; - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - - let extra = Option::::None(()); - - let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); - let threshold = 3; - let mut result = NNTrait::relu(@tensor, threshold); - - let data_0 = *result.data.at(0); - assert(data_0 == 0, 'result[0] == 0'); - - let data_1 = *result.data.at(1); - assert(data_1 == 0, 'result[1] == 0'); - - let data_2 = *result.data.at(2); - assert(data_2 == 3, 'result[2] == 3'); - - let data_3 = *result.data.at(3); - assert(data_3 == 4, 'result[3] == 4'); +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(2000000)] + fn relu() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = 1; + let val_2 = 2; + let val_3 = 3; + let val_4 = 4; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = Option::::None(()); + + let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); + let threshold = 3; + let mut result = NNTrait::relu(@tensor, threshold); + + let data_0 = *result.data.at(0); + assert(data_0 == 0, 'result[0] == 0'); + + let data_1 = *result.data.at(1); + assert(data_1 == 0, 'result[1] == 0'); + + let data_2 = *result.data.at(2); + assert(data_2 == 3, 'result[2] == 3'); + + let data_3 = *result.data.at(3); + assert(data_3 == 4, 'result[3] == 4'); + } } + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(2000000)] + fn relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 1; + let val_2 = 2; + let val_3 = 3; + let val_4 = 4; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = Option::::None(()); + + let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); + let threshold = 3; + let mut result = NNTrait::relu(@tensor, threshold); + + let data_0 = *result.data.at(0); + assert(data_0 == 0, 'result[0] == 0'); + + let data_1 = *result.data.at(1); + assert(data_1 == 0, 'result[1] == 0'); + + let data_2 = *result.data.at(2); + assert(data_2 == 3, 'result[2] == 3'); + + let data_3 = *result.data.at(3); + assert(data_3 == 4, 'result[3] == 4'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(2000000)] + fn relu() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 1; + let val_2 = 2; + let val_3 = 3; + let val_4 = 4; + let val_5 = 5; + let val_6 = 6; + let val_7 = 7; + let val_8 = 8; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + let extra = Option::::None(()); + + let mut tensor = TensorTrait::new(shape.span(), data.span(), extra); + let threshold = 3; + let mut result = NNTrait::relu(@tensor, threshold); + + let data_0 = *result.data.at(0); + assert(data_0 == 0, 'result[0] == 0'); + + let data_1 = *result.data.at(1); + assert(data_1 == 0, 'result[1] == 0'); + + let data_2 = *result.data.at(2); + assert(data_2 == 3, 'result[2] == 3'); + + let data_3 = *result.data.at(3); + assert(data_3 == 4, 'result[3] == 4'); + + let data_4 = *result.data.at(4); + assert(data_4 == 5, 'result[4] == 5'); + + let data_5 = *result.data.at(5); + assert(data_5 == 6, 'result[5] == 6'); + + let data_6 = *result.data.at(6); + assert(data_6 == 7, 'result[6] == 7'); + + let data_7 = *result.data.at(7); + assert(data_7 == 8, 'result[7] == 8'); + } +} + From 15ac01377b71e3cde5b5838cca8c66f7986a3016 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 13:53:09 +0300 Subject: [PATCH 044/126] refactor sigmoid tests --- .../functional/sigmoid/sigmoid_i32_test.cairo | 386 +++++++++++++++-- .../functional/sigmoid/sigmoid_u32_test.cairo | 398 ++++++++++++++++-- 2 files changed, 703 insertions(+), 81 deletions(-) diff --git a/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo b/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo index 928c08074..4652353ae 100644 --- a/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo +++ b/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo @@ -1,49 +1,363 @@ -use array::ArrayTrait; -use core::debug::PrintTrait; -use array::SpanTrait; -use core::Into; +// ===== 1D ===== // -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32::NN_i32; -use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use core::debug::PrintTrait; + use array::SpanTrait; + use core::Into; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; -#[test] -#[available_gas(5000000)] -fn sigmoid_i32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(2); + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(4); - let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(0, false); - let val_2 = IntegerTrait::new(1, false); - let val_3 = IntegerTrait::new(2, true); - let val_4 = IntegerTrait::new(254, false); + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(254, false); - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); - let mut result = NNTrait::sigmoid(@tensor); + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); - let data = *result.data.at(0).mag; - assert(data == 32768, 'result[0] == 4194304'); // 0.5 + let data = *result.data.at(0).mag; + assert(data == 4194304, 'result[0] == 4194304'); // 0.5 - let data = *result.data.at(1).mag; - assert(data == 47910, 'result[1] == 47910'); // 0.7310... + let data = *result.data.at(1).mag; + assert(data == 6132564, 'result[1] == 47910'); // 0.7310... - let data = *result.data.at(2).mag; - assert(data == 7812, 'result[2] == 7812'); // 0.11920... + let data = *result.data.at(2).mag; + assert(data == 999946, 'result[2] == 999946'); // 0.11920... - let data = *result.data.at(3).mag; - assert(data == 65536, 'result[3] == 65536'); // 1 + let data = *result.data.at(3).mag; + assert(data == 8388608, 'result[3] == 8388608'); // 1 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use core::debug::PrintTrait; + use array::SpanTrait; + use core::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(254, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 32768, 'result[0] == 32768'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 47910, 'result[1] == 47910'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 7812, 'result[2] == 7812'); // 0.11920... + + let data = *result.data.at(3).mag; + assert(data == 65536, 'result[3] == 65536'); // 1 + } + } } +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use core::debug::PrintTrait; + use array::SpanTrait; + use core::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(254, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 4194304, 'result[0] == 4194304'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 6132564, 'result[1] == 47910'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 999946, 'result[2] == 999946'); // 0.11920... + + let data = *result.data.at(3).mag; + assert(data == 8388608, 'result[3] == 8388608'); // 1 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use core::debug::PrintTrait; + use array::SpanTrait; + use core::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(254, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 32768, 'result[0] == 32768'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 47910, 'result[1] == 47910'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 7812, 'result[2] == 7812'); // 0.11920... + + let data = *result.data.at(3).mag; + assert(data == 65536, 'result[3] == 65536'); // 1 + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use core::debug::PrintTrait; + use array::SpanTrait; + use core::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(254, false); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(1, false); + let val_7 = IntegerTrait::new(2, true); + let val_8 = IntegerTrait::new(254, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 4194304, 'result[0] == 4194304'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 6132564, 'result[1] == 47910'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 999946, 'result[2] == 999946'); // 0.11920... + + let data = *result.data.at(3).mag; + assert(data == 8388608, 'result[3] == 8388608'); // 1 + + let data = *result.data.at(4).mag; + assert(data == 4194304, 'result[4] == 4194304'); // 0.5 + + let data = *result.data.at(5).mag; + assert(data == 6132564, 'result[5] == 47910'); // 0.7310... + + let data = *result.data.at(6).mag; + assert(data == 999946, 'result[6] == 999946'); // 0.11920... + + let data = *result.data.at(7).mag; + assert(data == 8388608, 'result[7] == 8388608'); // 1 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use core::debug::PrintTrait; + use array::SpanTrait; + use core::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(254, false); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(1, false); + let val_7 = IntegerTrait::new(2, true); + let val_8 = IntegerTrait::new(254, false); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 32768, 'result[0] == 32768'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 47910, 'result[1] == 47910'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 7812, 'result[2] == 7812'); // 0.11920... + + let data = *result.data.at(3).mag; + assert(data == 65536, 'result[3] == 65536'); // 1 + + let data = *result.data.at(4).mag; + assert(data == 32768, 'result[4] == 32768'); // 0.5 + + let data = *result.data.at(5).mag; + assert(data == 47910, 'result[5] == 47910'); // 0.7310... + + let data = *result.data.at(6).mag; + assert(data == 7812, 'result[6] == 7812'); // 0.11920... + + let data = *result.data.at(7).mag; + assert(data == 65536, 'result[7] == 65536'); // 1 + } + } +} diff --git a/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo b/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo index cffc26fd8..e3782d278 100644 --- a/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo +++ b/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo @@ -1,47 +1,355 @@ -use core::debug::PrintTrait; -use array::ArrayTrait; -use array::SpanTrait; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::numbers::signed_integer::integer_trait::IntegerTrait; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32::NN_u32; -use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; - -#[test] -#[available_gas(5000000)] -fn sigmoid_u32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(2); - - let mut data = ArrayTrait::::new(); - let val_1 = 0; - let val_2 = 1; - let val_3 = 2; - let val_4 = 254; - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; - - let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); - let mut result = NNTrait::sigmoid(@tensor); - - let data = *result.data.at(0).mag; - assert(data == 32768, 'result[0] == 4194304'); // 0.5 - - let data = *result.data.at(1).mag; - assert(data == 47910, 'result[1] == 47910'); // 0.7310... - - let data = *result.data.at(2).mag; - assert(data == 57724, 'result[2] == 57724'); // 0.8807... - - let data = *result.data.at(3).mag; - assert(data == 65536, 'result[3] == 65536'); // 1 +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use core::debug::PrintTrait; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::integer_trait::IntegerTrait; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 254; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 4194304, 'result[0] == 4194304'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 6132564, 'result[1] == 6132564'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 7388661, 'result[2] == 7388661'); // 0.8807... + + let data = *result.data.at(3).mag; + assert(data == 8388608, 'result[3] == 8388608'); // 1 + } + } + + #[cfg(test)] + mod fp16x16 { + use core::debug::PrintTrait; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::integer_trait::IntegerTrait; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 254; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 32768, 'result[0] == 32768'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 47910, 'result[1] == 47910'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 57724, 'result[2] == 57724'); // 0.8807... + + let data = *result.data.at(3).mag; + assert(data == 65536, 'result[3] == 65536'); // 1 + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use core::debug::PrintTrait; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::integer_trait::IntegerTrait; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 254; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 4194304, 'result[0] == 4194304'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 6132564, 'result[1] == 6132564'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 7388661, 'result[2] == 7388661'); // 0.8807... + + let data = *result.data.at(3).mag; + assert(data == 8388608, 'result[3] == 8388608'); // 1 + } + } + + #[cfg(test)] + mod fp16x16 { + use core::debug::PrintTrait; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::integer_trait::IntegerTrait; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 254; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 32768, 'result[0] == 32768'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 47910, 'result[1] == 47910'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 57724, 'result[2] == 57724'); // 0.8807... + + let data = *result.data.at(3).mag; + assert(data == 65536, 'result[3] == 65536'); // 1 + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use core::debug::PrintTrait; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::integer_trait::IntegerTrait; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 254; + let val_5 = 0; + let val_6 = 1; + let val_7 = 2; + let val_8 = 254; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 4194304, 'result[0] == 4194304'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 6132564, 'result[1] == 6132564'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 7388661, 'result[2] == 7388661'); // 0.8807... + + let data = *result.data.at(3).mag; + assert(data == 8388608, 'result[3] == 8388608'); // 1 + + let data = *result.data.at(4).mag; + assert(data == 4194304, 'result[4] == 4194304'); // 0.5 + + let data = *result.data.at(5).mag; + assert(data == 6132564, 'result[5] == 6132564'); // 0.7310... + + let data = *result.data.at(6).mag; + assert(data == 7388661, 'result[6] == 7388661'); // 0.8807... + + let data = *result.data.at(7).mag; + assert(data == 8388608, 'result[7] == 8388608'); // 1 + } + } + + #[cfg(test)] + mod fp16x16 { + use core::debug::PrintTrait; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::integer_trait::IntegerTrait; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedTrait, FixedImpl}; + + #[test] + #[available_gas(5000000)] + fn sigmoid() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 254; + let val_5 = 0; + let val_6 = 1; + let val_7 = 2; + let val_8 = 254; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::sigmoid(@tensor); + + let data = *result.data.at(0).mag; + assert(data == 32768, 'result[0] == 32768'); // 0.5 + + let data = *result.data.at(1).mag; + assert(data == 47910, 'result[1] == 47910'); // 0.7310... + + let data = *result.data.at(2).mag; + assert(data == 57724, 'result[2] == 57724'); // 0.8807... + + let data = *result.data.at(3).mag; + assert(data == 65536, 'result[3] == 65536'); // 1 + + let data = *result.data.at(4).mag; + assert(data == 32768, 'result[4] == 32768'); // 0.5 + + let data = *result.data.at(5).mag; + assert(data == 47910, 'result[5] == 47910'); // 0.7310... + + let data = *result.data.at(6).mag; + assert(data == 57724, 'result[6] == 57724'); // 0.8807... + + let data = *result.data.at(7).mag; + assert(data == 65536, 'result[7] == 65536'); // 1 + } + } } From 6fc44423fc962ee1a2aab85cb2ffa1e832f53e37 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 14:39:54 +0300 Subject: [PATCH 045/126] refactor softmax tests --- .../operators/nn/functional/softmax.cairo | 3 +- .../functional/softmax/softmax_i32_test.cairo | 268 ++++++++++++++++++ .../nn/functional/softmax/softmax_test.cairo | 34 --- .../functional/softmax/softmax_u32_test.cairo | 268 ++++++++++++++++++ 4 files changed, 538 insertions(+), 35 deletions(-) create mode 100644 src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo delete mode 100644 src/tests/operators/nn/functional/softmax/softmax_test.cairo create mode 100644 src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo diff --git a/src/tests/operators/nn/functional/softmax.cairo b/src/tests/operators/nn/functional/softmax.cairo index 9d1f26f3c..7618c4b2f 100644 --- a/src/tests/operators/nn/functional/softmax.cairo +++ b/src/tests/operators/nn/functional/softmax.cairo @@ -1 +1,2 @@ -mod softmax_test; \ No newline at end of file +mod softmax_i32_test; +mod softmax_u32_test; diff --git a/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo new file mode 100644 index 000000000..7231f4bdf --- /dev/null +++ b/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo @@ -0,0 +1,268 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Impl, FP8x23Into, FP8x23Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(20000000)] + fn softmax() { + let tensor = i32_tensor_1x3_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 755231, 'result[0] = 0.09003057'); + assert((*result.at(1)).into() == 2052931, 'result[1] = 0.24472847'); + assert((*result.at(2)).into() == 5580445, 'result[2] = 0.66524096'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(20000000)] + fn softmax() { + let tensor = i32_tensor_1x3_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 5900, 'result[0] = 0.09003057'); + assert((*result.at(1)).into() == 16038, 'result[1] = 0.24472847'); + assert((*result.at(2)).into() == 43596, 'result[2] = 0.66524096'); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(20000000)] + fn softmax() { + let tensor = i32_tensor_2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 999946, 'result[0] = 0.1192'); + assert((*result.at(1)).into() == 999946, 'result[1] = 0.1192'); + assert((*result.at(2)).into() == 7388661, 'result[2] = 0.8808'); + assert((*result.at(3)).into() == 7388661, 'result[3] = 0.8808'); + + let mut result = NNTrait::softmax(@tensor, 1).data; + + assert((*result.at(0)).into() == 2256044, 'result[0] = 0.2689'); + assert((*result.at(1)).into() == 6132563, 'result[1] = 0.7311'); + assert((*result.at(2)).into() == 2256043, 'result[2] = 0.2689'); + assert((*result.at(3)).into() == 6132564, 'result[4] = 0.7311'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(20000000)] + fn softmax() { + let tensor = i32_tensor_2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 7812, 'result[0] = 0.1192'); + assert((*result.at(1)).into() == 7812, 'result[1] = 0.1192'); + assert((*result.at(2)).into() == 57723, 'result[2] = 0.8808'); + assert((*result.at(3)).into() == 57723, 'result[3] = 0.8808'); + + let mut result = NNTrait::softmax(@tensor, 1).data; + + assert((*result.at(0)).into() == 17625, 'result[0] = 0.2689'); + assert((*result.at(1)).into() == 47910, 'result[1] = 0.7311'); + assert((*result.at(2)).into() == 17625, 'result[2] = 0.2689'); + assert((*result.at(3)).into() == 47910, 'result[4] = 0.7311'); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Impl, FP8x23Into, FP8x23Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(200000000)] + fn softmax() { + let tensor = i32_tensor_2x2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 150879, 'result[0] = 0.01798621'); + assert((*result.at(1)).into() == 150879, 'result[1] = 0.01798621'); + assert((*result.at(2)).into() == 150879, 'result[2] = 0.01798621'); + assert((*result.at(3)).into() == 150879, 'result[3] = 0.01798621'); + assert((*result.at(4)).into() == 8237728, 'result[4] = 0.01798621'); + assert((*result.at(5)).into() == 8237728, 'result[5] = 0.01798621'); + assert((*result.at(6)).into() == 8237728, 'result[6] = 0.01798621'); + assert((*result.at(7)).into() == 8237728, 'result[7] = 0.01798621'); + + let mut result = NNTrait::softmax(@tensor, 1).data; + + assert((*result.at(0)).into() == 999946, 'result[0] = 0.11920292'); + assert((*result.at(1)).into() == 999946, 'result[1] = 0.11920292'); + assert((*result.at(2)).into() == 7388661, 'result[2] = 0.88079708'); + assert((*result.at(3)).into() == 7388661, 'result[3] = 0.88079708'); + assert((*result.at(4)).into() == 999946, 'result[4] = 0.11920292'); + assert((*result.at(5)).into() == 999946, 'result[5] = 0.11920292'); + assert((*result.at(6)).into() == 7388661, 'result[6] = 0.88079708'); + assert((*result.at(7)).into() == 7388661, 'result[7] = 0.88079708'); + + let mut result = NNTrait::softmax(@tensor, 2).data; + + assert((*result.at(0)).into() == 2256044, 'result[0] = 0.26894142'); + assert((*result.at(1)).into() == 6132563, 'result[1] = 0.73105858'); + assert((*result.at(2)).into() == 2256043, 'result[2] = 0.26894142'); + assert((*result.at(3)).into() == 6132564, 'result[3] = 0.73105858'); + assert((*result.at(4)).into() == 2256044, 'result[4] = 0.26894142'); + assert((*result.at(5)).into() == 6132563, 'result[5] = 0.73105858'); + assert((*result.at(6)).into() == 2256044, 'result[6] = 0.26894142'); + assert((*result.at(7)).into() == 6132563, 'result[7] = 0.73105858'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + + #[test] + #[available_gas(200000000)] + fn softmax() { + let tensor = i32_tensor_2x2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 1178, 'result[0] = 0.01798621'); + assert((*result.at(1)).into() == 1178, 'result[1] = 0.01798621'); + assert((*result.at(2)).into() == 1178, 'result[2] = 0.01798621'); + assert((*result.at(3)).into() == 1178, 'result[3] = 0.01798621'); + assert((*result.at(4)).into() == 64357, 'result[4] = 0.01798621'); + assert((*result.at(5)).into() == 64357, 'result[5] = 0.01798621'); + assert((*result.at(6)).into() == 64357, 'result[6] = 0.01798621'); + assert((*result.at(7)).into() == 64357, 'result[7] = 0.01798621'); + + let mut result = NNTrait::softmax(@tensor, 1).data; + + assert((*result.at(0)).into() == 7812, 'result[0] = 0.11920292'); + assert((*result.at(1)).into() == 7812, 'result[1] = 0.11920292'); + assert((*result.at(2)).into() == 57723, 'result[2] = 0.88079708'); + assert((*result.at(3)).into() == 57723, 'result[3] = 0.88079708'); + assert((*result.at(4)).into() == 7812, 'result[4] = 0.11920292'); + assert((*result.at(5)).into() == 7812, 'result[5] = 0.11920292'); + assert((*result.at(6)).into() == 57723, 'result[6] = 0.88079708'); + assert((*result.at(7)).into() == 57723, 'result[7] = 0.88079708'); + + let mut result = NNTrait::softmax(@tensor, 2).data; + + assert((*result.at(0)).into() == 17625, 'result[0] = 0.26894142'); + assert((*result.at(1)).into() == 47910, 'result[1] = 0.73105858'); + assert((*result.at(2)).into() == 17625, 'result[2] = 0.26894142'); + assert((*result.at(3)).into() == 47910, 'result[3] = 0.73105858'); + assert((*result.at(4)).into() == 17625, 'result[4] = 0.26894142'); + assert((*result.at(5)).into() == 47910, 'result[5] = 0.73105858'); + assert((*result.at(6)).into() == 17625, 'result[6] = 0.26894142'); + assert((*result.at(7)).into() == 47910, 'result[7] = 0.73105858'); + } + } +} + diff --git a/src/tests/operators/nn/functional/softmax/softmax_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_test.cairo deleted file mode 100644 index d40fad2d1..000000000 --- a/src/tests/operators/nn/functional/softmax/softmax_test.cairo +++ /dev/null @@ -1,34 +0,0 @@ -use array::SpanTrait; -use traits::Into; - -use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::fixed_point::core::FixedImpl; -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32::NN_i32; - -use debug::print_felt252; - -#[test] -#[available_gas(20000000)] -fn softmax_test() { - let tensor = i32_tensor_2x2_helper(); - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); - - let mut result = NNTrait::softmax(@tensor, 0).data; - - assert((*result.at(0)).into() == 999946, 'result[0] = 0.1192'); - assert((*result.at(1)).into() == 999946, 'result[1] = 0.1192'); - assert((*result.at(2)).into() == 7388661, 'result[2] = 0.8808'); - assert((*result.at(3)).into() == 7388661, 'result[3] = 0.8808'); - - let mut result = NNTrait::softmax(@tensor, 1).data; - - assert((*result.at(0)).into() == 2256044, 'result[0] = 0.2689'); - assert((*result.at(1)).into() == 6132563, 'result[1] = 0.7311'); - assert((*result.at(2)).into() == 2256043, 'result[2] = 0.2689'); - assert((*result.at(3)).into() == 6132564, 'result[4] = 0.7311'); -} diff --git a/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo new file mode 100644 index 000000000..dfe4b4dde --- /dev/null +++ b/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo @@ -0,0 +1,268 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Impl, FP8x23Into, FP8x23Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(20000000)] + fn softmax() { + let tensor = u32_tensor_1x3_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 755231, 'result[0] = 0.09003057'); + assert((*result.at(1)).into() == 2052931, 'result[1] = 0.24472847'); + assert((*result.at(2)).into() == 5580445, 'result[2] = 0.66524096'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(20000000)] + fn softmax() { + let tensor = u32_tensor_1x3_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 5900, 'result[0] = 0.09003057'); + assert((*result.at(1)).into() == 16038, 'result[1] = 0.24472847'); + assert((*result.at(2)).into() == 43596, 'result[2] = 0.66524096'); + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(20000000)] + fn softmax() { + let tensor = u32_tensor_2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 999946, 'result[0] = 0.1192'); + assert((*result.at(1)).into() == 999946, 'result[1] = 0.1192'); + assert((*result.at(2)).into() == 7388661, 'result[2] = 0.8808'); + assert((*result.at(3)).into() == 7388661, 'result[3] = 0.8808'); + + let mut result = NNTrait::softmax(@tensor, 1).data; + + assert((*result.at(0)).into() == 2256044, 'result[0] = 0.2689'); + assert((*result.at(1)).into() == 6132563, 'result[1] = 0.7311'); + assert((*result.at(2)).into() == 2256043, 'result[2] = 0.2689'); + assert((*result.at(3)).into() == 6132564, 'result[4] = 0.7311'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(20000000)] + fn softmax() { + let tensor = u32_tensor_2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 7812, 'result[0] = 0.1192'); + assert((*result.at(1)).into() == 7812, 'result[1] = 0.1192'); + assert((*result.at(2)).into() == 57723, 'result[2] = 0.8808'); + assert((*result.at(3)).into() == 57723, 'result[3] = 0.8808'); + + let mut result = NNTrait::softmax(@tensor, 1).data; + + assert((*result.at(0)).into() == 17625, 'result[0] = 0.2689'); + assert((*result.at(1)).into() == 47910, 'result[1] = 0.7311'); + assert((*result.at(2)).into() == 17625, 'result[2] = 0.2689'); + assert((*result.at(3)).into() == 47910, 'result[4] = 0.7311'); + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{ + FP8x23Impl, FP8x23Into, FP8x23Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(200000000)] + fn softmax() { + let tensor = u32_tensor_2x2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 150879, 'result[0] = 0.01798621'); + assert((*result.at(1)).into() == 150879, 'result[1] = 0.01798621'); + assert((*result.at(2)).into() == 150879, 'result[2] = 0.01798621'); + assert((*result.at(3)).into() == 150879, 'result[3] = 0.01798621'); + assert((*result.at(4)).into() == 8237728, 'result[4] = 0.01798621'); + assert((*result.at(5)).into() == 8237728, 'result[5] = 0.01798621'); + assert((*result.at(6)).into() == 8237728, 'result[6] = 0.01798621'); + assert((*result.at(7)).into() == 8237728, 'result[7] = 0.01798621'); + + let mut result = NNTrait::softmax(@tensor, 1).data; + + assert((*result.at(0)).into() == 999946, 'result[0] = 0.11920292'); + assert((*result.at(1)).into() == 999946, 'result[1] = 0.11920292'); + assert((*result.at(2)).into() == 7388661, 'result[2] = 0.88079708'); + assert((*result.at(3)).into() == 7388661, 'result[3] = 0.88079708'); + assert((*result.at(4)).into() == 999946, 'result[4] = 0.11920292'); + assert((*result.at(5)).into() == 999946, 'result[5] = 0.11920292'); + assert((*result.at(6)).into() == 7388661, 'result[6] = 0.88079708'); + assert((*result.at(7)).into() == 7388661, 'result[7] = 0.88079708'); + + let mut result = NNTrait::softmax(@tensor, 2).data; + + assert((*result.at(0)).into() == 2256044, 'result[0] = 0.26894142'); + assert((*result.at(1)).into() == 6132563, 'result[1] = 0.73105858'); + assert((*result.at(2)).into() == 2256043, 'result[2] = 0.26894142'); + assert((*result.at(3)).into() == 6132564, 'result[3] = 0.73105858'); + assert((*result.at(4)).into() == 2256044, 'result[4] = 0.26894142'); + assert((*result.at(5)).into() == 6132563, 'result[5] = 0.73105858'); + assert((*result.at(6)).into() == 2256044, 'result[6] = 0.26894142'); + assert((*result.at(7)).into() == 6132563, 'result[7] = 0.73105858'); + } + } + + #[cfg(test)] + mod fp16x16 { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + + #[test] + #[available_gas(200000000)] + fn softmax() { + let tensor = u32_tensor_2x2x2_helper(); + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + let tensor = TensorTrait::new(tensor.shape, tensor.data, Option::Some(extra)); + + let mut result = NNTrait::softmax(@tensor, 0).data; + + assert((*result.at(0)).into() == 1178, 'result[0] = 0.01798621'); + assert((*result.at(1)).into() == 1178, 'result[1] = 0.01798621'); + assert((*result.at(2)).into() == 1178, 'result[2] = 0.01798621'); + assert((*result.at(3)).into() == 1178, 'result[3] = 0.01798621'); + assert((*result.at(4)).into() == 64357, 'result[4] = 0.01798621'); + assert((*result.at(5)).into() == 64357, 'result[5] = 0.01798621'); + assert((*result.at(6)).into() == 64357, 'result[6] = 0.01798621'); + assert((*result.at(7)).into() == 64357, 'result[7] = 0.01798621'); + + let mut result = NNTrait::softmax(@tensor, 1).data; + + assert((*result.at(0)).into() == 7812, 'result[0] = 0.11920292'); + assert((*result.at(1)).into() == 7812, 'result[1] = 0.11920292'); + assert((*result.at(2)).into() == 57723, 'result[2] = 0.88079708'); + assert((*result.at(3)).into() == 57723, 'result[3] = 0.88079708'); + assert((*result.at(4)).into() == 7812, 'result[4] = 0.11920292'); + assert((*result.at(5)).into() == 7812, 'result[5] = 0.11920292'); + assert((*result.at(6)).into() == 57723, 'result[6] = 0.88079708'); + assert((*result.at(7)).into() == 57723, 'result[7] = 0.88079708'); + + let mut result = NNTrait::softmax(@tensor, 2).data; + + assert((*result.at(0)).into() == 17625, 'result[0] = 0.26894142'); + assert((*result.at(1)).into() == 47910, 'result[1] = 0.73105858'); + assert((*result.at(2)).into() == 17625, 'result[2] = 0.26894142'); + assert((*result.at(3)).into() == 47910, 'result[3] = 0.73105858'); + assert((*result.at(4)).into() == 17625, 'result[4] = 0.26894142'); + assert((*result.at(5)).into() == 47910, 'result[5] = 0.73105858'); + assert((*result.at(6)).into() == 17625, 'result[6] = 0.26894142'); + assert((*result.at(7)).into() == 47910, 'result[7] = 0.73105858'); + } + } +} + From cba5acfd08e2cb86ece62a59db52d1eada35ef38 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 15:57:18 +0300 Subject: [PATCH 046/126] refactor softplus tests --- .../softplus/softplus_i32_test.cairo | 350 +++++++++++++++-- .../softplus/softplus_u32_test.cairo | 355 +++++++++++++++--- 2 files changed, 617 insertions(+), 88 deletions(-) diff --git a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo index 0b3ac1cde..eeebccfc3 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo @@ -1,42 +1,312 @@ -use core::option::OptionTrait; -use array::ArrayTrait; -use array::SpanTrait; -use traits::Into; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32::NN_i32; -use orion::numbers::fixed_point::core::FixedImpl; -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; - -#[test] -#[available_gas(50000000)] -fn softplus_i32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(2); - - let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(0, false); - let val_2 = IntegerTrait::new(1, false); - let val_3 = IntegerTrait::new(2, true); - let val_4 = IntegerTrait::new(3, true); - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); - let mut result = NNTrait::softplus(@tensor); - - assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 - assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 - assert((*result.data.at(2)).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 - assert((*result.data.at(3)).into() == 407580, 'result[3] == 407580'); // 0.04858729 +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data.at(2)).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 + assert((*result.data.at(3)).into() == 407580, 'result[3] == 407580'); // 0.04858729 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data.at(2)).into() == 8315, 'result[2] == 8315'); // 0.12692797 + assert((*result.data.at(3)).into() == 3182, 'result[3] == 3182'); // 0.04858729 + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data.at(2)).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 + assert((*result.data.at(3)).into() == 407580, 'result[3] == 407580'); // 0.04858729 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data.at(2)).into() == 8315, 'result[2] == 8315'); // 0.12692797 + assert((*result.data.at(3)).into() == 3182, 'result[3] == 3182'); // 0.04858729 + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(1, false); + let val_7 = IntegerTrait::new(2, true); + let val_8 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data.at(2)).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 + assert((*result.data.at(3)).into() == 407580, 'result[3] == 407580'); // 0.04858729 + assert((*result.data.at(4)).into() == 5814556, 'result[4] == 5814556'); // 0.6931452 + assert((*result.data.at(5)).into() == 11016447, 'result[5] == 11016447'); // 1.31326096 + assert((*result.data.at(6)).into() == 1064751, 'result[6] == 1064751'); // 0.12692797 + assert((*result.data.at(7)).into() == 407580, 'result[7] == 407580'); // 0.04858729 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16Into, FP16x16Print + }; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(1, false); + let val_7 = IntegerTrait::new(2, true); + let val_8 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data.at(2)).into() == 8315, 'result[2] == 8315'); // 0.12692797 + assert((*result.data.at(3)).into() == 3182, 'result[3] == 3182'); // 0.04858729 + assert((*result.data.at(4)).into() == 45355, 'result[4] == 45355'); // 0.6931452 + assert((*result.data.at(5)).into() == 86022, 'result[5] == 86022'); // 1.31326096 + assert((*result.data.at(6)).into() == 8315, 'result[6] == 8315'); // 0.12692797 + assert((*result.data.at(7)).into() == 3182, 'result[7] == 3182'); // 0.04858729 + } + } } diff --git a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo index 9da2bb101..e03679fc9 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo @@ -1,50 +1,309 @@ -use core::option::OptionTrait; -use array::ArrayTrait; -use array::SpanTrait; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::numbers::signed_integer::integer_trait::IntegerTrait; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32::NN_u32; -use orion::numbers::fixed_point::core::FixedTrait; - -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; -use orion::numbers::fixed_point::core::FixedImpl; - -#[test] -#[available_gas(5000000)] -fn softplus_u32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(2); - - let mut data = ArrayTrait::::new(); - let val_1 = 0; - let val_2 = 1; - let val_3 = 2; - let val_4 = 3; - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); - let mut result = NNTrait::softplus(@tensor); - - let data = *result.data.at(0); - assert(data == FixedTrait::new(5814556, false), 'result[0] == 5814556'); // 0.6931452 - - let data = *result.data.at(1); - assert(data == FixedTrait::new(11016447, false), 'result[1] == 11016447'); // 1.31326096 - - let data = *result.data.at(2); - assert(data == FixedTrait::new(17841964, false), 'result[2] == 17841964'); // 2.12692796 - - let data = *result.data.at(3); - assert(data == FixedTrait::new(25573406, false), 'result[3] == 25573406'); // 3.04858728 +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data.at(2)).into() == 17841964, 'result[2] == 17841964'); // 2.1269 + assert((*result.data.at(3)).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert( + (*result.data.at(2)).into() == 139388, 'result[2] == 139388' + ); // 2.12689208984375 + assert((*result.data.at(3)).into() == 199788, 'result[3] == 199788'); // 3.04852294 + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert( + (*result.data.at(2)).into() == 17841964, 'result[2] == 17841964' + ); // 2.12689208984375 + assert((*result.data.at(3)).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert( + (*result.data.at(2)).into() == 139388, 'result[2] == 139388' + ); // 2.12689208984375 + assert((*result.data.at(3)).into() == 199788, 'result[3] == 199788'); // 3.04852294 + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + let val_5 = 0; + let val_6 = 1; + let val_7 = 2; + let val_8 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert( + (*result.data.at(2)).into() == 17841964, 'result[2] == 17841964' + ); // 2.12689208984375 + assert((*result.data.at(3)).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 + assert((*result.data.at(4)).into() == 5814556, 'result[4] == 5814556'); // 0.6931452 + assert((*result.data.at(5)).into() == 11016447, 'result[5] == 11016447'); // 1.31326096 + assert((*result.data.at(6)).into() == 17841964, 'result[6] == 17841964'); // 2.1269278 + assert((*result.data.at(7)).into() == 25573406, 'result[7] == 25573406'); // 3.0485875 + } + } + + #[cfg(test)] + mod fp16x16 { + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + + #[test] + #[available_gas(50000000)] + fn softplus() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + let val_5 = 0; + let val_6 = 1; + let val_7 = 2; + let val_8 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softplus(@tensor); + + assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert( + (*result.data.at(2)).into() == 139388, 'result[2] == 139388' + ); // 2.12689208984375 + assert((*result.data.at(3)).into() == 199788, 'result[3] == 199788'); // 3.04852294 + assert((*result.data.at(4)).into() == 45355, 'result[4] == 45355'); // 0.6931452 + assert((*result.data.at(5)).into() == 86022, 'result[5] == 86022'); // 1.31326096 + assert( + (*result.data.at(6)).into() == 139388, 'result[6] == 139388' + ); // 2.12689208984375 + assert((*result.data.at(7)).into() == 199788, 'result[7] == 199788'); // 3.04852294 + } + } } From 80f097befe03c9223382b7a1f5480ec175af0997 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 16:14:25 +0300 Subject: [PATCH 047/126] refactor softsign --- .../softplus/softplus_i32_test.cairo | 2 +- .../softsign/softsign_i32_test.cairo | 345 ++++++++++++-- .../softsign/softsign_u32_test.cairo | 430 ++++++++++++++++-- 3 files changed, 686 insertions(+), 91 deletions(-) diff --git a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo index eeebccfc3..c0070deb6 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo @@ -188,7 +188,7 @@ mod tensor_2D { } } -// ===== 2D ===== // +// ===== 3D ===== // #[cfg(test)] mod tensor_3D { diff --git a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo index d7c8417a8..794030012 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo @@ -1,43 +1,306 @@ -use core::option::OptionTrait; -use array::ArrayTrait; -use array::SpanTrait; -use traits::Into; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_i32::NN_i32; -use orion::numbers::fixed_point::core::FixedImpl; -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; - -#[test] -#[available_gas(2000000)] -fn softsign_i32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(2); - - let mut data = ArrayTrait::::new(); - let val_1 = IntegerTrait::new(0, false); - let val_2 = IntegerTrait::new(1, false); - let val_3 = IntegerTrait::new(2, true); - let val_4 = IntegerTrait::new(3, true); - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); - let mut result = NNTrait::softsign(@tensor); - - let data = *result.data.at(0); - assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 - assert((*result.data.at(1)).into() == 4194304, 'result[1] == 4194304'); // 0.5 - assert((*result.data.at(2)).into() == -5592405, 'result[2] == 5592405'); // -0.67 - assert((*result.data.at(3)).into() == -6291456, 'result[3] == 6291456'); // -0.75 +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use core::option::OptionTrait; + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data.at(1)).into() == 4194304, 'result[1] == 4194304'); // 0.5 + assert((*result.data.at(2)).into() == -5592405, 'result[2] == 5592405'); // -0.67 + assert((*result.data.at(3)).into() == -6291456, 'result[3] == 6291456'); // -0.75 + } + } + + mod fp16x16 { + use core::option::OptionTrait; + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data.at(1)).into() == 32768, 'result[1] == 32768'); // 0.5 + assert((*result.data.at(2)).into() == -43690, 'result[2] == 43690'); // -0.67 + assert((*result.data.at(3)).into() == -49152, 'result[3] == 49152'); // -0.75 + } + } +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use core::option::OptionTrait; + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data.at(1)).into() == 4194304, 'result[1] == 4194304'); // 0.5 + assert((*result.data.at(2)).into() == -5592405, 'result[2] == 5592405'); // -0.67 + assert((*result.data.at(3)).into() == -6291456, 'result[3] == 6291456'); // -0.75 + } + } + + mod fp16x16 { + use core::option::OptionTrait; + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data.at(1)).into() == 32768, 'result[1] == 32768'); // 0.5 + assert((*result.data.at(2)).into() == -43690, 'result[2] == 43690'); // -0.67 + assert((*result.data.at(3)).into() == -49152, 'result[3] == 49152'); // -0.75 + } + } } +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use core::option::OptionTrait; + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Into}; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(1, false); + let val_7 = IntegerTrait::new(2, true); + let val_8 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data.at(1)).into() == 4194304, 'result[1] == 4194304'); // 0.5 + assert((*result.data.at(2)).into() == -5592405, 'result[2] == 5592405'); // -0.67 + assert((*result.data.at(3)).into() == -6291456, 'result[3] == 6291456'); // -0.75 + assert((*result.data.at(4)).into() == 0, 'result[4] == 0'); // 0 + assert((*result.data.at(5)).into() == 4194304, 'result[5] == 4194304'); // 0.5 + assert((*result.data.at(6)).into() == -5592405, 'result[6] == 5592405'); // -0.67 + assert((*result.data.at(7)).into() == -6291456, 'result[7] == 6291456'); // -0.75 + } + } + + mod fp16x16 { + use core::option::OptionTrait; + use array::ArrayTrait; + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_i32::NN_i32; + use orion::numbers::fixed_point::core::FixedImpl; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Into}; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = IntegerTrait::new(0, false); + let val_2 = IntegerTrait::new(1, false); + let val_3 = IntegerTrait::new(2, true); + let val_4 = IntegerTrait::new(3, true); + let val_5 = IntegerTrait::new(0, false); + let val_6 = IntegerTrait::new(1, false); + let val_7 = IntegerTrait::new(2, true); + let val_8 = IntegerTrait::new(3, true); + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data.at(1)).into() == 32768, 'result[1] == 32768'); // 0.5 + assert((*result.data.at(2)).into() == -43690, 'result[2] == 43690'); // -0.67 + assert((*result.data.at(3)).into() == -49152, 'result[3] == 49152'); // -0.75 + assert((*result.data.at(4)).into() == 0, 'result[4] == 0'); // 0 + assert((*result.data.at(5)).into() == 32768, 'result[5] == 32768'); // 0.5 + assert((*result.data.at(6)).into() == -43690, 'result[6] == 43690'); // -0.67 + assert((*result.data.at(7)).into() == -49152, 'result[7] == 49152'); // -0.75 + } + } +} diff --git a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo index a5158dbd3..50ee03076 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo @@ -1,51 +1,383 @@ -use core::option::OptionTrait; -use core::traits::Into; -use array::ArrayTrait; -use array::SpanTrait; - -use orion::operators::tensor::core::{TensorTrait, ExtraParams}; -use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; -use orion::operators::nn::core::NNTrait; -use orion::operators::nn::implementations::impl_nn_u32::NN_u32; -use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; - -use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; -use orion::numbers::fixed_point::core::FixedImpl; - -#[test] -#[available_gas(2000000)] -fn softsign_u32_test() { - let mut shape = ArrayTrait::::new(); - shape.append(2); - shape.append(2); - - let mut data = ArrayTrait::::new(); - let val_1 = 0; - let val_2 = 1; - let val_3 = 2; - let val_4 = 3; - - data.append(val_1); - data.append(val_2); - data.append(val_3); - data.append(val_4); - - let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; - - let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); - let mut result = NNTrait::softsign(@tensor); - - let data = *result.data.at(0); - assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 - - let data = *result.data.at(1); - assert(data == FixedTrait::new(4194304, false), 'result[1] == 4194304'); // 0.5 - - let data = *result.data.at(2); - assert(data == FixedTrait::new(5592405, false), 'result[2] == 5592405'); // 0.67 - - let data = *result.data.at(3); - assert(data == FixedTrait::new(6291456, false), 'result[3] == 6291456'); // 0.75 +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + #[cfg(test)] + mod fp8x23 { + use core::option::OptionTrait; + use core::traits::Into; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + use orion::numbers::fixed_point::core::FixedImpl; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(4); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(4194304, false), 'result[1] == 4194304'); // 0.5 + + let data = *result.data.at(2); + assert(data == FixedTrait::new(5592405, false), 'result[2] == 5592405'); // 0.67 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(6291456, false), 'result[3] == 6291456'); // 0.75 + } + } + + mod fp16x16 { + use core::option::OptionTrait; + use core::traits::Into; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16PartialEq + }; + use orion::numbers::fixed_point::core::FixedImpl; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(32768, false), 'result[1] == 32768'); // 0.5 + + let data = *result.data.at(2); + assert(data == FixedTrait::new(43690, false), 'result[2] == 43690'); // 0.67 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(49152, false), 'result[3] == 49152'); // 0.75 + } + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + #[cfg(test)] + mod fp8x23 { + use core::option::OptionTrait; + use core::traits::Into; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + use orion::numbers::fixed_point::core::FixedImpl; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(4194304, false), 'result[1] == 4194304'); // 0.5 + + let data = *result.data.at(2); + assert(data == FixedTrait::new(5592405, false), 'result[2] == 5592405'); // 0.67 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(6291456, false), 'result[3] == 6291456'); // 0.75 + } + } + + mod fp16x16 { + use core::option::OptionTrait; + use core::traits::Into; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16PartialEq + }; + use orion::numbers::fixed_point::core::FixedImpl; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(32768, false), 'result[1] == 32768'); // 0.5 + + let data = *result.data.at(2); + assert(data == FixedTrait::new(43690, false), 'result[2] == 43690'); // 0.67 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(49152, false), 'result[3] == 49152'); // 0.75 + } + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + #[cfg(test)] + mod fp8x23 { + use core::option::OptionTrait; + use core::traits::Into; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23PartialEq}; + use orion::numbers::fixed_point::core::FixedImpl; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + let val_5 = 0; + let val_6 = 1; + let val_7 = 2; + let val_8 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(4194304, false), 'result[1] == 4194304'); // 0.5 + + let data = *result.data.at(2); + assert(data == FixedTrait::new(5592405, false), 'result[2] == 5592405'); // 0.67 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(6291456, false), 'result[3] == 6291456'); // 0.75 + + let data = *result.data.at(4); + assert(data == FixedTrait::new(0, false), 'result[4] == 0'); // 0 + + let data = *result.data.at(5); + assert(data == FixedTrait::new(4194304, false), 'result[5] == 4194304'); // 0.5 + + let data = *result.data.at(6); + assert(data == FixedTrait::new(5592405, false), 'result[6] == 5592405'); // 0.67 + + let data = *result.data.at(7); + assert(data == FixedTrait::new(6291456, false), 'result[7] == 6291456'); // 0.75 + } + } + + mod fp16x16 { + use core::option::OptionTrait; + use core::traits::Into; + use array::ArrayTrait; + use array::SpanTrait; + + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait}; + use orion::operators::nn::core::NNTrait; + use orion::operators::nn::implementations::impl_nn_u32::NN_u32; + use orion::numbers::fixed_point::core::{FixedType, FixedTrait}; + + use orion::numbers::fixed_point::implementations::impl_16x16::{ + FP16x16Impl, FP16x16PartialEq + }; + use orion::numbers::fixed_point::core::FixedImpl; + + #[test] + #[available_gas(2000000)] + fn softsign() { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(2); + + let mut data = ArrayTrait::::new(); + let val_1 = 0; + let val_2 = 1; + let val_3 = 2; + let val_4 = 3; + let val_5 = 0; + let val_6 = 1; + let val_7 = 2; + let val_8 = 3; + + data.append(val_1); + data.append(val_2); + data.append(val_3); + data.append(val_4); + data.append(val_5); + data.append(val_6); + data.append(val_7); + data.append(val_8); + + let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP16x16(())) }; + + let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); + let mut result = NNTrait::softsign(@tensor); + + let data = *result.data.at(0); + assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 + + let data = *result.data.at(1); + assert(data == FixedTrait::new(32768, false), 'result[1] == 32768'); // 0.5 + + let data = *result.data.at(2); + assert(data == FixedTrait::new(43690, false), 'result[2] == 43690'); // 0.67 + + let data = *result.data.at(3); + assert(data == FixedTrait::new(49152, false), 'result[3] == 49152'); // 0.75 + + let data = *result.data.at(4); + assert(data == FixedTrait::new(0, false), 'result[4] == 0'); // 0 + + let data = *result.data.at(5); + assert(data == FixedTrait::new(32768, false), 'result[5] == 32768'); // 0.5 + + let data = *result.data.at(6); + assert(data == FixedTrait::new(43690, false), 'result[6] == 43690'); // 0.67 + + let data = *result.data.at(7); + assert(data == FixedTrait::new(49152, false), 'result[7] == 49152'); // 0.75 + } + } } From 8bd493b5046d1e4668c132fe6d5897d8ba691607 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 16:15:02 +0300 Subject: [PATCH 048/126] Update CHANGELOG.md --- docs/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 1e2af543f..3fb8083a1 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] - 2023-06-21 +### Changed +- Refactor nn tests to cover n-dimensions + +## [Unreleased] - 2023-06-21 + ### Changed - Refactor tensor tests to cover n-dimensions From 4552895f3f1e03cba900be0808a41cd4f6b1bc84 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 22 Jun 2023 16:17:53 +0300 Subject: [PATCH 049/126] rename modules in tests --- .../nn/functional/leaky_relu/leaky_relu_i32_test.cairo | 6 +++--- .../nn/functional/leaky_relu/leaky_relu_u32_test.cairo | 6 +++--- .../nn/functional/logsoftmax/logsoftmax_i32_test.cairo | 6 +++--- .../nn/functional/logsoftmax/logsoftmax_u32_test.cairo | 6 +++--- src/tests/operators/nn/functional/relu/relu_i32_test.cairo | 6 +++--- src/tests/operators/nn/functional/relu/relu_u32_test.cairo | 6 +++--- .../operators/nn/functional/sigmoid/sigmoid_i32_test.cairo | 6 +++--- .../operators/nn/functional/sigmoid/sigmoid_u32_test.cairo | 6 +++--- .../operators/nn/functional/softmax/softmax_i32_test.cairo | 6 +++--- .../operators/nn/functional/softmax/softmax_u32_test.cairo | 6 +++--- .../nn/functional/softplus/softplus_i32_test.cairo | 6 +++--- .../nn/functional/softplus/softplus_u32_test.cairo | 6 +++--- .../nn/functional/softsign/softsign_i32_test.cairo | 6 +++--- .../nn/functional/softsign/softsign_u32_test.cairo | 6 +++--- 14 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo index 14c395c09..8bbd9f983 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -111,7 +111,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -222,7 +222,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo index 95f2b655a..1092f4f9b 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -118,7 +118,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -237,7 +237,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo index 5dc140dbf..4a2d04eae 100644 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; @@ -78,7 +78,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; @@ -171,7 +171,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo index ced70e521..93949e54b 100644 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; @@ -78,7 +78,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; @@ -171,7 +171,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; diff --git a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo index 7fb45f98d..a9c67582c 100644 --- a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { use array::ArrayTrait; use array::SpanTrait; use traits::Into; @@ -45,7 +45,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { use array::ArrayTrait; use array::SpanTrait; use traits::Into; @@ -90,7 +90,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { use array::ArrayTrait; use array::SpanTrait; use traits::Into; diff --git a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo index 1fd1a488c..9f13bd17a 100644 --- a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { use array::ArrayTrait; use array::SpanTrait; @@ -51,7 +51,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { use array::ArrayTrait; use array::SpanTrait; @@ -102,7 +102,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { use array::ArrayTrait; use array::SpanTrait; diff --git a/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo b/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo index 4652353ae..879e8187f 100644 --- a/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo +++ b/src/tests/operators/nn/functional/sigmoid/sigmoid_i32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -107,7 +107,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -215,7 +215,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; diff --git a/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo b/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo index e3782d278..cc2781368 100644 --- a/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo +++ b/src/tests/operators/nn/functional/sigmoid/sigmoid_u32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use core::debug::PrintTrait; @@ -104,7 +104,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use core::debug::PrintTrait; @@ -209,7 +209,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use core::debug::PrintTrait; diff --git a/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo index 7231f4bdf..2a9306462 100644 --- a/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo +++ b/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; @@ -68,7 +68,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; @@ -148,7 +148,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; diff --git a/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo index dfe4b4dde..39d9daeb2 100644 --- a/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo +++ b/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; @@ -68,7 +68,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; @@ -148,7 +148,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::SpanTrait; diff --git a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo index c0070deb6..82f33ae41 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -95,7 +95,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -191,7 +191,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; diff --git a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo index e03679fc9..ac3c2c0f1 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -92,7 +92,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; @@ -187,7 +187,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use array::ArrayTrait; diff --git a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo index 794030012..e19c1283d 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use core::option::OptionTrait; @@ -94,7 +94,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use core::option::OptionTrait; @@ -188,7 +188,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use core::option::OptionTrait; diff --git a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo index 50ee03076..52c5ec550 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo @@ -1,7 +1,7 @@ // ===== 1D ===== // #[cfg(test)] -mod tensor_1D { +mod input_1D { #[cfg(test)] mod fp8x23 { use core::option::OptionTrait; @@ -114,7 +114,7 @@ mod tensor_1D { // ===== 2D ===== // #[cfg(test)] -mod tensor_2D { +mod input_2D { #[cfg(test)] mod fp8x23 { use core::option::OptionTrait; @@ -228,7 +228,7 @@ mod tensor_2D { // ===== 3D ===== // #[cfg(test)] -mod tensor_3D { +mod input_3D { #[cfg(test)] mod fp8x23 { use core::option::OptionTrait; From 1ff628d31daf4b3f8747d9c326693ee1cee0d7bf Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Fri, 23 Jun 2023 13:25:47 +0300 Subject: [PATCH 050/126] replace .at with IndexView --- src/operators/tensor/helpers.cairo | 6 +- .../linalg/matmul/matmul_fp/fp16x16.cairo | 8 +- .../linalg/matmul/matmul_fp/fp8x23.cairo | 8 +- .../tensor/linalg/matmul/matmul_i32.cairo | 8 +- .../tensor/linalg/matmul/matmul_u32.cairo | 8 +- .../transpose/transpose_fp/fp16x16.cairo | 4 +- .../transpose/transpose_fp/fp8x23.cairo | 4 +- .../linalg/transpose/transpose_i32.cairo | 4 +- .../linalg/transpose/transpose_u32.cairo | 4 +- .../tensor/math/argmax/helpers.cairo | 4 +- .../tensor/math/argmin/helpers.cairo | 4 +- .../arithmetic/arithmetic_fp/fp16x16.cairo | 8 +- .../arithmetic/arithmetic_fp/fp8x23.cairo | 8 +- .../math/arithmetic/arithmetic_i32.cairo | 8 +- .../math/arithmetic/arithmetic_u32.cairo | 8 +- .../tensor/math/equal/equal_fp/fp16x16.cairo | 2 +- .../tensor/math/equal/equal_fp/fp8x23.cairo | 2 +- .../tensor/math/equal/equal_i32.cairo | 2 +- .../tensor/math/equal/equal_u32.cairo | 2 +- .../math/greater/greater_fp/fp16x16.cairo | 2 +- .../math/greater/greater_fp/fp8x23.cairo | 2 +- .../tensor/math/greater/greater_i32.cairo | 2 +- .../tensor/math/greater/greater_u32.cairo | 2 +- .../greater_equal_fp/fp16x16.cairo | 2 +- .../greater_equal_fp/fp8x23.cairo | 2 +- .../greater_equal/greater_equal_i32.cairo | 2 +- .../greater_equal/greater_equal_u32.cairo | 2 +- .../tensor/math/less/less_fp/fp16x16.cairo | 2 +- .../tensor/math/less/less_fp/fp8x23.cairo | 2 +- src/operators/tensor/math/less/less_i32.cairo | 2 +- src/operators/tensor/math/less/less_u32.cairo | 2 +- .../less_equal/less_equal_fp/fp16x16.cairo | 2 +- .../less_equal/less_equal_fp/fp8x23.cairo | 2 +- .../math/less_equal/less_equal_i32.cairo | 2 +- .../math/less_equal/less_equal_u32.cairo | 2 +- .../reduce_sum/reduce_sum_fp/fp16x16.cairo | 4 +- .../reduce_sum/reduce_sum_fp/fp8x23.cairo | 4 +- .../math/reduce_sum/reduce_sum_i32.cairo | 4 +- .../math/reduce_sum/reduce_sum_u32.cairo | 4 +- .../leaky_relu/leaky_relu_i32_test.cairo | 36 +-- .../leaky_relu/leaky_relu_u32_test.cairo | 48 +-- .../logsoftmax/logsoftmax_i32_test.cairo | 16 +- .../logsoftmax/logsoftmax_u32_test.cairo | 16 +- .../nn/functional/relu/relu_i32_test.cairo | 20 +- .../nn/functional/relu/relu_u32_test.cairo | 32 +- .../functional/softmax/softmax_i32_test.cairo | 140 ++++----- .../functional/softmax/softmax_u32_test.cairo | 140 ++++----- .../softplus/softplus_i32_test.cairo | 64 ++-- .../softplus/softplus_u32_test.cairo | 64 ++-- .../softsign/softsign_i32_test.cairo | 64 ++-- .../softsign/softsign_u32_test.cairo | 64 ++-- .../stride_fp_test/stride_fp16x16_test.cairo | 12 +- .../stride_fp_test/stride_fp8x23_test.cairo | 12 +- .../tensor/core/stride/stride_i32_test.cairo | 12 +- .../tensor/core/stride/stride_u32_test.cairo | 12 +- .../transpose_fp16x16_test.cairo | 182 ++++++------ .../transpose_fp8x23_test.cairo | 182 ++++++------ .../core/transpose/transpose_u32_test.cairo | 182 ++++++------ .../operators/tensor/core/unravel_index.cairo | 12 +- .../argmax_fp_test/argmax_fp16x16_test.cairo | 78 ++--- .../argmax_fp_test/argmax_fp8x23_test.cairo | 78 ++--- .../tensor/math/argmax/argmax_i32_test.cairo | 78 ++--- .../tensor/math/argmax/argmax_u32_test.cairo | 76 ++--- .../argmin_fp_test/argmin_fp16x16_test.cairo | 78 ++--- .../argmin_fp_test/argmin_fp8x23_test.cairo | 78 ++--- .../tensor/math/argmin/argmin_i32_test.cairo | 78 ++--- .../tensor/math/argmin/argmin_u32_test.cairo | 76 ++--- .../arithmetic_fp16x16_test.cairo | 278 +++++++++--------- .../arithmetic_fp8x23_test.cairo | 278 +++++++++--------- .../math/arithmetic/arithmetic_i32_test.cairo | 278 +++++++++--------- .../math/arithmetic/arithmetic_u32_test.cairo | 278 +++++++++--------- .../ceil/ceil_fp_test/ceil_fp16x16_test.cairo | 32 +- .../ceil/ceil_fp_test/ceil_fp8x23_test.cairo | 32 +- .../equal_fp_test/equal_fp16x16_test.cairo | 120 ++++---- .../equal_fp_test/equal_fp8x23_test.cairo | 120 ++++---- .../tensor/math/equal/equal_i32_test.cairo | 120 ++++---- .../tensor/math/equal/equal_u32_test.cairo | 114 +++---- .../greater_fp16x16_test.cairo | 154 +++++----- .../greater_fp_test/greater_fp8x23_test.cairo | 154 +++++----- .../math/greater/greater_i32_test.cairo | 154 +++++----- .../math/greater/greater_u32_test.cairo | 158 +++++----- .../greater_equal_fp16x16_test.cairo | 154 +++++----- .../greater_equal_fp8x23_test.cairo | 154 +++++----- .../greater_equal_i32_test.cairo | 154 +++++----- .../greater_equal_u32_test.cairo | 158 +++++----- .../less/less_fp_test/less_fp16x16_test.cairo | 154 +++++----- .../less/less_fp_test/less_fp8x23_test.cairo | 154 +++++----- .../tensor/math/less/less_i32_test.cairo | 154 +++++----- .../tensor/math/less/less_u32_test.cairo | 158 +++++----- .../less_equal_fp16x16_test.cairo | 154 +++++----- .../less_equal_fp8x23_test.cairo | 154 +++++----- .../math/less_equal/less_equal_i32_test.cairo | 154 +++++----- .../math/less_equal/less_equal_u32_test.cairo | 158 +++++----- 93 files changed, 3105 insertions(+), 3105 deletions(-) diff --git a/src/operators/tensor/helpers.cairo b/src/operators/tensor/helpers.cairo index f0b340f50..d823c5cfd 100644 --- a/src/operators/tensor/helpers.cairo +++ b/src/operators/tensor/helpers.cairo @@ -174,7 +174,7 @@ fn permutation_output_shape(input_shape: Span, mut axes: Span) -> break (); } - output_shape.append(*input_shape.at(*axes.pop_front().unwrap())); + output_shape.append(*input_shape[*axes.pop_front().unwrap()]); axis += 1; }; @@ -211,9 +211,9 @@ fn combine_indices(output_indices: Span, axis_index: usize, axis: usize) if n == axis { result.append(axis_index); } else if n > axis { - result.append(*output_indices.at(n - 1_usize)); + result.append(*output_indices[n - 1_usize]); } else { - result.append(*output_indices.at(n)); + result.append(*output_indices[n]); } n += 1; diff --git a/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo b/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo index b90ce0bd9..c06e3d3d0 100644 --- a/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo +++ b/src/operators/tensor/linalg/matmul/matmul_fp/fp16x16.cairo @@ -90,9 +90,9 @@ fn dot_product(mut vec1: Span, mut vec2: Span) -> FixedTyp fn matrix_multiply( mat1: Span, mat1_shape: Span, mat2: Span, mat2_shape: Span ) -> Tensor { - let m = *mat1_shape.at(0); - let n = *mat1_shape.at(1); - let p = *mat2_shape.at(1); + let m = *mat1_shape[0]; + let n = *mat1_shape[1]; + let p = *mat2_shape[1]; let mut result_data = ArrayTrait::new(); let mut result_shape = ArrayTrait::new(); @@ -123,7 +123,7 @@ fn matrix_multiply( let mat1_index = i * n + k; let mat2_index = k * p + j; - sum += *mat1.at(mat1_index) * *mat2.at(mat2_index); + sum += *mat1[mat1_index] * *mat2[mat2_index]; k += 1; }; diff --git a/src/operators/tensor/linalg/matmul/matmul_fp/fp8x23.cairo b/src/operators/tensor/linalg/matmul/matmul_fp/fp8x23.cairo index 7abc41c03..bbc9d6150 100644 --- a/src/operators/tensor/linalg/matmul/matmul_fp/fp8x23.cairo +++ b/src/operators/tensor/linalg/matmul/matmul_fp/fp8x23.cairo @@ -88,9 +88,9 @@ fn dot_product(mut vec1: Span, mut vec2: Span) -> FixedTyp fn matrix_multiply( mat1: Span, mat1_shape: Span, mat2: Span, mat2_shape: Span ) -> Tensor { - let m = *mat1_shape.at(0); - let n = *mat1_shape.at(1); - let p = *mat2_shape.at(1); + let m = *mat1_shape[0]; + let n = *mat1_shape[1]; + let p = *mat2_shape[1]; let mut result_data = ArrayTrait::new(); let mut result_shape = ArrayTrait::new(); @@ -121,7 +121,7 @@ fn matrix_multiply( let mat1_index = i * n + k; let mat2_index = k * p + j; - sum += *mat1.at(mat1_index) * *mat2.at(mat2_index); + sum += *mat1[mat1_index] * *mat2[mat2_index]; k += 1; }; diff --git a/src/operators/tensor/linalg/matmul/matmul_i32.cairo b/src/operators/tensor/linalg/matmul/matmul_i32.cairo index 55b0cdbe7..49822afa8 100644 --- a/src/operators/tensor/linalg/matmul/matmul_i32.cairo +++ b/src/operators/tensor/linalg/matmul/matmul_i32.cairo @@ -87,9 +87,9 @@ fn dot_product(mut vec1: Span, mut vec2: Span) -> i32 { fn matrix_multiply( mat1: Span, mat1_shape: Span, mat2: Span, mat2_shape: Span ) -> Tensor { - let m = *mat1_shape.at(0); - let n = *mat1_shape.at(1); - let p = *mat2_shape.at(1); + let m = *mat1_shape[0]; + let n = *mat1_shape[1]; + let p = *mat2_shape[1]; let mut result_data = ArrayTrait::new(); let mut result_shape = ArrayTrait::new(); @@ -120,7 +120,7 @@ fn matrix_multiply( let mat1_index = i * n + k; let mat2_index = k * p + j; - sum += *mat1.at(mat1_index) * *mat2.at(mat2_index); + sum += *mat1[mat1_index] * *mat2[mat2_index]; k += 1; }; diff --git a/src/operators/tensor/linalg/matmul/matmul_u32.cairo b/src/operators/tensor/linalg/matmul/matmul_u32.cairo index 126c93a23..774caf270 100644 --- a/src/operators/tensor/linalg/matmul/matmul_u32.cairo +++ b/src/operators/tensor/linalg/matmul/matmul_u32.cairo @@ -86,9 +86,9 @@ fn dot_product(mut vec1: Span, mut vec2: Span) -> u32 { fn matrix_multiply( mat1: Span, mat1_shape: Span, mat2: Span, mat2_shape: Span ) -> Tensor { - let m = *mat1_shape.at(0); - let n = *mat1_shape.at(1); - let p = *mat2_shape.at(1); + let m = *mat1_shape[0]; + let n = *mat1_shape[1]; + let p = *mat2_shape[1]; let mut result_data = ArrayTrait::new(); let mut result_shape = ArrayTrait::new(); @@ -119,7 +119,7 @@ fn matrix_multiply( let mat1_index = i * n + k; let mat2_index = k * p + j; - sum += *mat1.at(mat1_index) * *mat2.at(mat2_index); + sum += *mat1[mat1_index] * *mat2[mat2_index]; k += 1; }; diff --git a/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo b/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo index 17069aa28..910b9bdd2 100644 --- a/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_fp/fp16x16.cairo @@ -39,12 +39,12 @@ fn transpose(self: @Tensor, axes: Span) -> Tensor { } let input_axis = find_axis(axes, output_axis); - input_indices.append(*output_indices.at(input_axis)); + input_indices.append(*output_indices[input_axis]); output_axis += 1; }; let input_index = ravel_index(*self.shape, input_indices.span()); - output_data.append(*(*self.data).at(input_index)); + output_data.append(*(*self.data)[input_index]); output_index += 1; }; diff --git a/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo b/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo index a1f0aaa23..79344cd7d 100644 --- a/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_fp/fp8x23.cairo @@ -39,12 +39,12 @@ fn transpose(self: @Tensor, axes: Span) -> Tensor { } let input_axis = find_axis(axes, output_axis); - input_indices.append(*output_indices.at(input_axis)); + input_indices.append(*output_indices[input_axis]); output_axis += 1; }; let input_index = ravel_index(*self.shape, input_indices.span()); - output_data.append(*(*self.data).at(input_index)); + output_data.append(*(*self.data)[input_index]); output_index += 1; }; diff --git a/src/operators/tensor/linalg/transpose/transpose_i32.cairo b/src/operators/tensor/linalg/transpose/transpose_i32.cairo index b080033d9..0945a1d11 100644 --- a/src/operators/tensor/linalg/transpose/transpose_i32.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_i32.cairo @@ -38,12 +38,12 @@ fn transpose(self: @Tensor, axes: Span) -> Tensor { } let input_axis = find_axis(axes, output_axis); - input_indices.append(*output_indices.at(input_axis)); + input_indices.append(*output_indices[input_axis]); output_axis += 1; }; let input_index = ravel_index(*self.shape, input_indices.span()); - output_data.append(*(*self.data).at(input_index)); + output_data.append(*(*self.data)[input_index]); output_index += 1; }; diff --git a/src/operators/tensor/linalg/transpose/transpose_u32.cairo b/src/operators/tensor/linalg/transpose/transpose_u32.cairo index b576651cc..7e294cba0 100644 --- a/src/operators/tensor/linalg/transpose/transpose_u32.cairo +++ b/src/operators/tensor/linalg/transpose/transpose_u32.cairo @@ -37,12 +37,12 @@ fn transpose(self: @Tensor, axes: Span) -> Tensor { } let input_axis = find_axis(axes, output_axis); - input_indices.append(*output_indices.at(input_axis)); + input_indices.append(*output_indices[input_axis]); output_axis += 1; }; let input_index = ravel_index(*self.shape, input_indices.span()); - output_data.append(*(*self.data).at(input_index)); + output_data.append(*(*self.data)[input_index]); output_index += 1; }; diff --git a/src/operators/tensor/math/argmax/helpers.cairo b/src/operators/tensor/math/argmax/helpers.cairo index cb9810e9c..c45ef8c0b 100644 --- a/src/operators/tensor/math/argmax/helpers.cairo +++ b/src/operators/tensor/math/argmax/helpers.cairo @@ -97,13 +97,13 @@ fn find_argmax< ) -> usize { check_gas(); - if axis_index == *(*input.shape).at(axis) { + if axis_index == *(*input.shape)[axis] { return argmax; } let input_indices = combine_indices(output_indices, axis_index, axis); let input_index = ravel_index(*input.shape, input_indices); - let ele = *(*input.data).at(input_index); + let ele = *(*input.data)[input_index]; let (new_max_value, new_argmax) = if ele > max_value { (ele, axis_index) diff --git a/src/operators/tensor/math/argmin/helpers.cairo b/src/operators/tensor/math/argmin/helpers.cairo index e76d9720c..5a2d8372f 100644 --- a/src/operators/tensor/math/argmin/helpers.cairo +++ b/src/operators/tensor/math/argmin/helpers.cairo @@ -99,13 +99,13 @@ fn find_argmin< T, ) -> usize { check_gas(); - if axis_index == *(*input.shape).at(axis) { + if axis_index == *(*input.shape)[axis] { return argmin; } let input_indices = combine_indices(output_indices, axis_index, axis); let input_index = ravel_index(*input.shape, input_indices); - let ele = *(*input.data).at(input_index); + let ele = *(*input.data)[input_index]; let (new_min_value, new_argmin) = if ele < min_value { (ele, axis_index) diff --git a/src/operators/tensor/math/arithmetic/arithmetic_fp/fp16x16.cairo b/src/operators/tensor/math/arithmetic/arithmetic_fp/fp16x16.cairo index 63a72f60d..21f368209 100644 --- a/src/operators/tensor/math/arithmetic/arithmetic_fp/fp16x16.cairo +++ b/src/operators/tensor/math/arithmetic/arithmetic_fp/fp16x16.cairo @@ -38,7 +38,7 @@ fn add(self: @Tensor, other: @Tensor) -> Tensor let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) + *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] + *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -76,7 +76,7 @@ fn sub(self: @Tensor, other: @Tensor) -> Tensor let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) - *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] - *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -114,7 +114,7 @@ fn mul(self: @Tensor, other: @Tensor) -> Tensor let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) * *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] * *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -152,7 +152,7 @@ fn div(self: @Tensor, other: @Tensor) -> Tensor let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) / *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] / *(*other.data)[indices_other]); n += 1; if n == num_elements { diff --git a/src/operators/tensor/math/arithmetic/arithmetic_fp/fp8x23.cairo b/src/operators/tensor/math/arithmetic/arithmetic_fp/fp8x23.cairo index 0721b4cd0..008e1da02 100644 --- a/src/operators/tensor/math/arithmetic/arithmetic_fp/fp8x23.cairo +++ b/src/operators/tensor/math/arithmetic/arithmetic_fp/fp8x23.cairo @@ -38,7 +38,7 @@ fn add(self: @Tensor, other: @Tensor) -> Tensor let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) + *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] + *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -76,7 +76,7 @@ fn sub(self: @Tensor, other: @Tensor) -> Tensor let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) - *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] - *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -114,7 +114,7 @@ fn mul(self: @Tensor, other: @Tensor) -> Tensor let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) * *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] * *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -152,7 +152,7 @@ fn div(self: @Tensor, other: @Tensor) -> Tensor let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) / *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] / *(*other.data)[indices_other]); n += 1; if n == num_elements { diff --git a/src/operators/tensor/math/arithmetic/arithmetic_i32.cairo b/src/operators/tensor/math/arithmetic/arithmetic_i32.cairo index d223dc872..eb9bec9f6 100644 --- a/src/operators/tensor/math/arithmetic/arithmetic_i32.cairo +++ b/src/operators/tensor/math/arithmetic/arithmetic_i32.cairo @@ -36,7 +36,7 @@ fn add(self: @Tensor, other: @Tensor) -> Tensor { let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) + *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] + *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -74,7 +74,7 @@ fn sub(self: @Tensor, other: @Tensor) -> Tensor { let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) - *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] - *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -112,7 +112,7 @@ fn mul(self: @Tensor, other: @Tensor) -> Tensor { let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) * *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] * *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -150,7 +150,7 @@ fn div(self: @Tensor, other: @Tensor) -> Tensor { let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) / *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] / *(*other.data)[indices_other]); n += 1; if n == num_elements { diff --git a/src/operators/tensor/math/arithmetic/arithmetic_u32.cairo b/src/operators/tensor/math/arithmetic/arithmetic_u32.cairo index 8c09cbdfb..3711ca7b9 100644 --- a/src/operators/tensor/math/arithmetic/arithmetic_u32.cairo +++ b/src/operators/tensor/math/arithmetic/arithmetic_u32.cairo @@ -35,7 +35,7 @@ fn add(self: @Tensor, other: @Tensor) -> Tensor { let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) + *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] + *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -73,7 +73,7 @@ fn sub(self: @Tensor, other: @Tensor) -> Tensor { let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) - *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] - *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -111,7 +111,7 @@ fn mul(self: @Tensor, other: @Tensor) -> Tensor { let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) * *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] * *(*other.data)[indices_other]); n += 1; if n == num_elements { @@ -149,7 +149,7 @@ fn div(self: @Tensor, other: @Tensor) -> Tensor { let indices_self = broadcast_index_mapping(*self.shape, indices_broadcasted); let indices_other = broadcast_index_mapping(*other.shape, indices_broadcasted); - result.append(*(*self.data).at(indices_self) / *(*other.data).at(indices_other)); + result.append(*(*self.data)[indices_self] / *(*other.data)[indices_other]); n += 1; if n == num_elements { diff --git a/src/operators/tensor/math/equal/equal_fp/fp16x16.cairo b/src/operators/tensor/math/equal/equal_fp/fp16x16.cairo index bd125e995..beee00fb8 100644 --- a/src/operators/tensor/math/equal/equal_fp/fp16x16.cairo +++ b/src/operators/tensor/math/equal/equal_fp/fp16x16.cairo @@ -35,7 +35,7 @@ fn equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; if bigger_current_index == smaller_current_index { data_result.append(1); diff --git a/src/operators/tensor/math/equal/equal_fp/fp8x23.cairo b/src/operators/tensor/math/equal/equal_fp/fp8x23.cairo index 1a20386cd..d458b0663 100644 --- a/src/operators/tensor/math/equal/equal_fp/fp8x23.cairo +++ b/src/operators/tensor/math/equal/equal_fp/fp8x23.cairo @@ -35,7 +35,7 @@ fn equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; if bigger_current_index == smaller_current_index { data_result.append(1); diff --git a/src/operators/tensor/math/equal/equal_i32.cairo b/src/operators/tensor/math/equal/equal_i32.cairo index 1eb6789ce..861b24b49 100644 --- a/src/operators/tensor/math/equal/equal_i32.cairo +++ b/src/operators/tensor/math/equal/equal_i32.cairo @@ -31,7 +31,7 @@ fn equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; if bigger_current_index == smaller_current_index { data_result.append(1); diff --git a/src/operators/tensor/math/equal/equal_u32.cairo b/src/operators/tensor/math/equal/equal_u32.cairo index c3dc4812b..862b0bd7b 100644 --- a/src/operators/tensor/math/equal/equal_u32.cairo +++ b/src/operators/tensor/math/equal/equal_u32.cairo @@ -29,7 +29,7 @@ fn equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; if bigger_current_index == smaller_current_index { data_result.append(1); diff --git a/src/operators/tensor/math/greater/greater_fp/fp16x16.cairo b/src/operators/tensor/math/greater/greater_fp/fp16x16.cairo index 2c8024c7b..8890d3d25 100644 --- a/src/operators/tensor/math/greater/greater_fp/fp16x16.cairo +++ b/src/operators/tensor/math/greater/greater_fp/fp16x16.cairo @@ -33,7 +33,7 @@ fn greater(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/greater/greater_fp/fp8x23.cairo b/src/operators/tensor/math/greater/greater_fp/fp8x23.cairo index 9364f2d6c..216a85695 100644 --- a/src/operators/tensor/math/greater/greater_fp/fp8x23.cairo +++ b/src/operators/tensor/math/greater/greater_fp/fp8x23.cairo @@ -34,7 +34,7 @@ fn greater(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/greater/greater_i32.cairo b/src/operators/tensor/math/greater/greater_i32.cairo index ba1937587..627950dce 100644 --- a/src/operators/tensor/math/greater/greater_i32.cairo +++ b/src/operators/tensor/math/greater/greater_i32.cairo @@ -31,7 +31,7 @@ fn greater(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/greater/greater_u32.cairo b/src/operators/tensor/math/greater/greater_u32.cairo index 3d8a4e238..07f747b5d 100644 --- a/src/operators/tensor/math/greater/greater_u32.cairo +++ b/src/operators/tensor/math/greater/greater_u32.cairo @@ -30,7 +30,7 @@ fn greater(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/greater_equal/greater_equal_fp/fp16x16.cairo b/src/operators/tensor/math/greater_equal/greater_equal_fp/fp16x16.cairo index 9e9ed22cd..97cc22982 100644 --- a/src/operators/tensor/math/greater_equal/greater_equal_fp/fp16x16.cairo +++ b/src/operators/tensor/math/greater_equal/greater_equal_fp/fp16x16.cairo @@ -32,7 +32,7 @@ fn greater_equal(y: @Tensor, z: @Tensor) -> Tensor }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/greater_equal/greater_equal_fp/fp8x23.cairo b/src/operators/tensor/math/greater_equal/greater_equal_fp/fp8x23.cairo index 041c471bf..20cdbb87b 100644 --- a/src/operators/tensor/math/greater_equal/greater_equal_fp/fp8x23.cairo +++ b/src/operators/tensor/math/greater_equal/greater_equal_fp/fp8x23.cairo @@ -33,7 +33,7 @@ fn greater_equal(y: @Tensor, z: @Tensor) -> Tensor }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/greater_equal/greater_equal_i32.cairo b/src/operators/tensor/math/greater_equal/greater_equal_i32.cairo index 855932a36..188bec517 100644 --- a/src/operators/tensor/math/greater_equal/greater_equal_i32.cairo +++ b/src/operators/tensor/math/greater_equal/greater_equal_i32.cairo @@ -31,7 +31,7 @@ fn greater_equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/greater_equal/greater_equal_u32.cairo b/src/operators/tensor/math/greater_equal/greater_equal_u32.cairo index f030e89c1..421d3fb2b 100644 --- a/src/operators/tensor/math/greater_equal/greater_equal_u32.cairo +++ b/src/operators/tensor/math/greater_equal/greater_equal_u32.cairo @@ -30,7 +30,7 @@ fn greater_equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/less/less_fp/fp16x16.cairo b/src/operators/tensor/math/less/less_fp/fp16x16.cairo index 4e9dc16d2..9cc07988f 100644 --- a/src/operators/tensor/math/less/less_fp/fp16x16.cairo +++ b/src/operators/tensor/math/less/less_fp/fp16x16.cairo @@ -33,7 +33,7 @@ fn less(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/less/less_fp/fp8x23.cairo b/src/operators/tensor/math/less/less_fp/fp8x23.cairo index fbebe1d6e..4b0d6c1f0 100644 --- a/src/operators/tensor/math/less/less_fp/fp8x23.cairo +++ b/src/operators/tensor/math/less/less_fp/fp8x23.cairo @@ -33,7 +33,7 @@ fn less(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/less/less_i32.cairo b/src/operators/tensor/math/less/less_i32.cairo index ca31dc6b0..21ee238a9 100644 --- a/src/operators/tensor/math/less/less_i32.cairo +++ b/src/operators/tensor/math/less/less_i32.cairo @@ -32,7 +32,7 @@ fn less(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/less/less_u32.cairo b/src/operators/tensor/math/less/less_u32.cairo index 8db1299e9..7736e6acd 100644 --- a/src/operators/tensor/math/less/less_u32.cairo +++ b/src/operators/tensor/math/less/less_u32.cairo @@ -30,7 +30,7 @@ fn less(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/less_equal/less_equal_fp/fp16x16.cairo b/src/operators/tensor/math/less_equal/less_equal_fp/fp16x16.cairo index 56b9217ba..acfb76205 100644 --- a/src/operators/tensor/math/less_equal/less_equal_fp/fp16x16.cairo +++ b/src/operators/tensor/math/less_equal/less_equal_fp/fp16x16.cairo @@ -32,7 +32,7 @@ fn less_equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/less_equal/less_equal_fp/fp8x23.cairo b/src/operators/tensor/math/less_equal/less_equal_fp/fp8x23.cairo index 93a4dda2b..e03ce80d4 100644 --- a/src/operators/tensor/math/less_equal/less_equal_fp/fp8x23.cairo +++ b/src/operators/tensor/math/less_equal/less_equal_fp/fp8x23.cairo @@ -32,7 +32,7 @@ fn less_equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/less_equal/less_equal_i32.cairo b/src/operators/tensor/math/less_equal/less_equal_i32.cairo index bd82d7616..5e55113e7 100644 --- a/src/operators/tensor/math/less_equal/less_equal_i32.cairo +++ b/src/operators/tensor/math/less_equal/less_equal_i32.cairo @@ -31,7 +31,7 @@ fn less_equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/less_equal/less_equal_u32.cairo b/src/operators/tensor/math/less_equal/less_equal_u32.cairo index a2bc4f093..c3cf78c88 100644 --- a/src/operators/tensor/math/less_equal/less_equal_u32.cairo +++ b/src/operators/tensor/math/less_equal/less_equal_u32.cairo @@ -30,7 +30,7 @@ fn less_equal(y: @Tensor, z: @Tensor) -> Tensor { }; let bigger_current_index = *bigger_data.pop_front().unwrap(); - let smaller_current_index = *smaller_data.at(smaller_index); + let smaller_current_index = *smaller_data[smaller_index]; let (y_value, z_value) = if retains_input_order { (smaller_current_index, bigger_current_index) diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo index bdcbc295e..aa1579ada 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp16x16.cairo @@ -71,7 +71,7 @@ fn accumulate_sum( output_indices: Span, axis: usize ) -> FixedType { - let axis_len = *(input_shape).at(axis); + let axis_len = *(input_shape)[axis]; let mut acc = FixedTrait::new(0, false); let mut axis_index: usize = 0; @@ -86,7 +86,7 @@ fn accumulate_sum( let input_indices = combine_indices(output_indices, axis_index, axis); let input_index = ravel_index(input_shape, input_indices); - let ele = *(input_data).at(input_index); + let ele = *(input_data)[input_index]; acc += ele; axis_index += 1; }; diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo index 58c649291..1023c975a 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_fp/fp8x23.cairo @@ -71,7 +71,7 @@ fn accumulate_sum( output_indices: Span, axis: usize ) -> FixedType { - let axis_len = *(input_shape).at(axis); + let axis_len = *(input_shape)[axis]; let mut acc = FixedTrait::new(0, false); let mut axis_index: usize = 0; @@ -86,7 +86,7 @@ fn accumulate_sum( let input_indices = combine_indices(output_indices, axis_index, axis); let input_index = ravel_index(input_shape, input_indices); - let ele = *(input_data).at(input_index); + let ele = *(input_data)[input_index]; acc += ele; axis_index += 1; }; diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo index 1d2fb803e..8ddceb873 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_i32.cairo @@ -66,7 +66,7 @@ fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { fn accumulate_sum( mut input_data: Span, input_shape: Span, output_indices: Span, axis: usize ) -> i32 { - let axis_len = *(input_shape).at(axis); + let axis_len = *(input_shape)[axis]; let mut acc = IntegerTrait::new(0, false); let mut axis_index: usize = 0; @@ -81,7 +81,7 @@ fn accumulate_sum( let input_indices = combine_indices(output_indices, axis_index, axis); let input_index = ravel_index(input_shape, input_indices); - let ele = *(input_data).at(input_index); + let ele = *(input_data)[input_index]; acc += ele; axis_index += 1; }; diff --git a/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo b/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo index 4d5fa6db3..ffb9fa548 100644 --- a/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo +++ b/src/operators/tensor/math/reduce_sum/reduce_sum_u32.cairo @@ -65,7 +65,7 @@ fn reduce_sum(self: @Tensor, axis: usize, keepdims: bool) -> Tensor { fn accumulate_sum( mut input_data: Span, input_shape: Span, output_indices: Span, axis: usize ) -> u32 { - let axis_len = *(input_shape).at(axis); + let axis_len = *(input_shape)[axis]; let mut acc = 0; let mut axis_index: usize = 0; @@ -80,7 +80,7 @@ fn accumulate_sum( let input_indices = combine_indices(output_indices, axis_index, axis); let input_index = ravel_index(input_shape, input_indices); - let ele = *(input_data).at(input_index); + let ele = *(input_data)[input_index]; acc += ele; axis_index += 1; }; diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo index 8bbd9f983..8bb769b76 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_i32_test.cairo @@ -45,11 +45,11 @@ mod input_1D { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 + assert((*result.data[0]).into() == 8388608, 'result[0] == 8388608'); // 1 assert( - (*result.data.at(3)).into() == -1677722, 'result[3] == - 1677722' + (*result.data[3]).into() == -1677722, 'result[3] == - 1677722' ); // 2 * 0.1 = - 0.2 - assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + assert((*result.data[5]).into() == 0, 'result[5] == 0'); } } @@ -98,11 +98,11 @@ mod input_1D { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - assert((*result.data.at(0)).into() == 65536, 'result[0] == 65536'); // 1 + assert((*result.data[0]).into() == 65536, 'result[0] == 65536'); // 1 assert( - (*result.data.at(3)).into() == -13108, 'result[3] == - 13108' + (*result.data[3]).into() == -13108, 'result[3] == - 13108' ); // 2 * 0.1 = - 0.2 - assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + assert((*result.data[5]).into() == 0, 'result[5] == 0'); } } } @@ -156,11 +156,11 @@ mod input_2D { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 + assert((*result.data[0]).into() == 8388608, 'result[0] == 8388608'); // 1 assert( - (*result.data.at(3)).into() == -1677722, 'result[3] == - 1677722' + (*result.data[3]).into() == -1677722, 'result[3] == - 1677722' ); // 2 * 0.1 = - 0.2 - assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + assert((*result.data[5]).into() == 0, 'result[5] == 0'); } } @@ -210,11 +210,11 @@ mod input_2D { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - assert((*result.data.at(0)).into() == 65536, 'result[0] == 65536'); // 1 + assert((*result.data[0]).into() == 65536, 'result[0] == 65536'); // 1 assert( - (*result.data.at(3)).into() == -13108, 'result[3] == - 13108' + (*result.data[3]).into() == -13108, 'result[3] == - 13108' ); // 2 * 0.1 = - 0.2 - assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + assert((*result.data[5]).into() == 0, 'result[5] == 0'); } } } @@ -272,11 +272,11 @@ mod input_3D { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - assert((*result.data.at(0)).into() == 8388608, 'result[0] == 8388608'); // 1 + assert((*result.data[0]).into() == 8388608, 'result[0] == 8388608'); // 1 assert( - (*result.data.at(3)).into() == -1677722, 'result[3] == - 1677722' + (*result.data[3]).into() == -1677722, 'result[3] == - 1677722' ); // 2 * 0.1 = - 0.2 - assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + assert((*result.data[5]).into() == 0, 'result[5] == 0'); } } @@ -331,11 +331,11 @@ mod input_3D { let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - assert((*result.data.at(0)).into() == 65536, 'result[0] == 65536'); // 1 + assert((*result.data[0]).into() == 65536, 'result[0] == 65536'); // 1 assert( - (*result.data.at(3)).into() == -13108, 'result[3] == - 13108' + (*result.data[3]).into() == -13108, 'result[3] == - 13108' ); // 2 * 0.1 = - 0.2 - assert((*result.data.at(5)).into() == 0, 'result[5] == 0'); + assert((*result.data[5]).into() == 0, 'result[5] == 0'); } } } diff --git a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo index 1092f4f9b..67e1984a5 100644 --- a/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/leaky_relu/leaky_relu_u32_test.cairo @@ -43,16 +43,16 @@ mod input_1D { let threshold = 3; let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(33554432, false), 'result[0] == 33554432'); // 4 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(25165824, false), 'result[1] == 25165824'); // 3 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(838861, false), 'result[3] == 838861'); // 0.1 - let data = *result.data.at(5); + let data = *result.data[5]; assert(data == FixedTrait::new(0, false), 'result[5] == 0'); } } @@ -100,16 +100,16 @@ mod input_1D { let threshold = 3; let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(262144, false), 'result[0] == 262144'); // 4 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(196608, false), 'result[1] == 196608'); // 3 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(6554, false), 'result[3] == 6554'); // 0.1 - let data = *result.data.at(5); + let data = *result.data[5]; assert(data == FixedTrait::new(0, false), 'result[5] == 0'); } } @@ -161,16 +161,16 @@ mod input_2D { let threshold = 3; let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(33554432, false), 'result[0] == 33554432'); // 4 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(25165824, false), 'result[1] == 25165824'); // 3 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(838861, false), 'result[3] == 838861'); // 0.1 - let data = *result.data.at(5); + let data = *result.data[5]; assert(data == FixedTrait::new(0, false), 'result[5] == 0'); } } @@ -219,16 +219,16 @@ mod input_2D { let threshold = 3; let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(262144, false), 'result[0] == 262144'); // 4 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(196608, false), 'result[1] == 196608'); // 3 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(6554, false), 'result[3] == 6554'); // 0.1 - let data = *result.data.at(5); + let data = *result.data[5]; assert(data == FixedTrait::new(0, false), 'result[5] == 0'); } } @@ -285,16 +285,16 @@ mod input_3D { let threshold = 3; let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(33554432, false), 'result[0] == 33554432'); // 4 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(25165824, false), 'result[1] == 25165824'); // 3 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(838861, false), 'result[3] == 838861'); // 0.1 - let data = *result.data.at(5); + let data = *result.data[5]; assert(data == FixedTrait::new(0, false), 'result[5] == 0'); } } @@ -348,16 +348,16 @@ mod input_3D { let threshold = 3; let mut result = NNTrait::leaky_relu(@tensor, @alpha, threshold); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(262144, false), 'result[0] == 262144'); // 4 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(196608, false), 'result[1] == 196608'); // 3 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(6554, false), 'result[3] == 6554'); // 0.1 - let data = *result.data.at(5); + let data = *result.data[5]; assert(data == FixedTrait::new(0, false), 'result[5] == 0'); } } diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo index 4a2d04eae..15268d878 100644 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_i32_test.cairo @@ -108,10 +108,10 @@ mod input_2D { let mut result = NNTrait::logsoftmax(@tensor, 1).data; - assert((*result.at(0)).into() == -11016451, 'result[0] = -1.3134'); - assert((*result.at(1)).into() == -2627827, 'result[1] = -0.3132'); - assert((*result.at(2)).into() == -11016460, 'result[2] = -1.3134'); - assert((*result.at(3)).into() == -2627829, 'result[3] = -0.3132'); + assert((*result[0]).into() == -11016451, 'result[0] = -1.3134'); + assert((*result[1]).into() == -2627827, 'result[1] = -0.3132'); + assert((*result[2]).into() == -11016460, 'result[2] = -1.3134'); + assert((*result[3]).into() == -2627829, 'result[3] = -0.3132'); } #[test] @@ -152,10 +152,10 @@ mod input_2D { let mut result = NNTrait::logsoftmax(@tensor, 1).data; - assert((*result.at(0)).into() == -86024, 'result[0] = -1.3134'); - assert((*result.at(1)).into() == -20523, 'result[1] = -0.3132'); - assert((*result.at(2)).into() == -86024, 'result[2] = -1.3134'); - assert((*result.at(3)).into() == -20523, 'result[3] = -0.3132'); + assert((*result[0]).into() == -86024, 'result[0] = -1.3134'); + assert((*result[1]).into() == -20523, 'result[1] = -0.3132'); + assert((*result[2]).into() == -86024, 'result[2] = -1.3134'); + assert((*result[3]).into() == -20523, 'result[3] = -0.3132'); } #[test] diff --git a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo index 93949e54b..7b4f52f9a 100644 --- a/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo +++ b/src/tests/operators/nn/functional/logsoftmax/logsoftmax_u32_test.cairo @@ -108,10 +108,10 @@ mod input_2D { let mut result = NNTrait::logsoftmax(@tensor, 1).data; - assert((*result.at(0)).into() == -11016451, 'result[0] = -1.3134'); - assert((*result.at(1)).into() == -2627827, 'result[1] = -0.3132'); - assert((*result.at(2)).into() == -11016460, 'result[2] = -1.3134'); - assert((*result.at(3)).into() == -2627829, 'result[3] = -0.3132'); + assert((*result[0]).into() == -11016451, 'result[0] = -1.3134'); + assert((*result[1]).into() == -2627827, 'result[1] = -0.3132'); + assert((*result[2]).into() == -11016460, 'result[2] = -1.3134'); + assert((*result[3]).into() == -2627829, 'result[3] = -0.3132'); } #[test] @@ -152,10 +152,10 @@ mod input_2D { let mut result = NNTrait::logsoftmax(@tensor, 1).data; - assert((*result.at(0)).into() == -86024, 'result[0] = -1.3134'); - assert((*result.at(1)).into() == -20523, 'result[1] = -0.3132'); - assert((*result.at(2)).into() == -86024, 'result[2] = -1.3134'); - assert((*result.at(3)).into() == -20523, 'result[3] = -0.3132'); + assert((*result[0]).into() == -86024, 'result[0] = -1.3134'); + assert((*result[1]).into() == -20523, 'result[1] = -0.3132'); + assert((*result[2]).into() == -86024, 'result[2] = -1.3134'); + assert((*result[3]).into() == -20523, 'result[3] = -0.3132'); } #[test] diff --git a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo index a9c67582c..c93d75bd7 100644 --- a/src/tests/operators/nn/functional/relu/relu_i32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_i32_test.cairo @@ -36,9 +36,9 @@ mod input_1D { let mut result = NNTrait::relu(@tensor, threshold); - let data_0 = *result.data.at(0); - assert((*result.data.at(0)).into() == 1, 'result[0] == 1'); - assert((*result.data.at(3)).into() == 0, 'result[3] == 0'); + let data_0 = *result.data[0]; + assert((*result.data[0]).into() == 1, 'result[0] == 1'); + assert((*result.data[3]).into() == 0, 'result[3] == 0'); } } @@ -81,9 +81,9 @@ mod input_2D { let mut result = NNTrait::relu(@tensor, threshold); - let data_0 = *result.data.at(0); - assert((*result.data.at(0)).into() == 1, 'result[0] == 1'); - assert((*result.data.at(3)).into() == 0, 'result[3] == 0'); + let data_0 = *result.data[0]; + assert((*result.data[0]).into() == 1, 'result[0] == 1'); + assert((*result.data[3]).into() == 0, 'result[3] == 0'); } } @@ -135,9 +135,9 @@ mod input_3D { let mut result = NNTrait::relu(@tensor, threshold); - let data_0 = *result.data.at(0); - assert((*result.data.at(0)).into() == 1, 'result[0] == 1'); - assert((*result.data.at(3)).into() == 0, 'result[3] == 0'); - assert((*result.data.at(5)).into() == 2, 'result[6] == 2'); + let data_0 = *result.data[0]; + assert((*result.data[0]).into() == 1, 'result[0] == 1'); + assert((*result.data[3]).into() == 0, 'result[3] == 0'); + assert((*result.data[5]).into() == 2, 'result[6] == 2'); } } diff --git a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo index 9f13bd17a..44c54d373 100644 --- a/src/tests/operators/nn/functional/relu/relu_u32_test.cairo +++ b/src/tests/operators/nn/functional/relu/relu_u32_test.cairo @@ -34,16 +34,16 @@ mod input_1D { let threshold = 3; let mut result = NNTrait::relu(@tensor, threshold); - let data_0 = *result.data.at(0); + let data_0 = *result.data[0]; assert(data_0 == 0, 'result[0] == 0'); - let data_1 = *result.data.at(1); + let data_1 = *result.data[1]; assert(data_1 == 0, 'result[1] == 0'); - let data_2 = *result.data.at(2); + let data_2 = *result.data[2]; assert(data_2 == 3, 'result[2] == 3'); - let data_3 = *result.data.at(3); + let data_3 = *result.data[3]; assert(data_3 == 4, 'result[3] == 4'); } } @@ -85,16 +85,16 @@ mod input_2D { let threshold = 3; let mut result = NNTrait::relu(@tensor, threshold); - let data_0 = *result.data.at(0); + let data_0 = *result.data[0]; assert(data_0 == 0, 'result[0] == 0'); - let data_1 = *result.data.at(1); + let data_1 = *result.data[1]; assert(data_1 == 0, 'result[1] == 0'); - let data_2 = *result.data.at(2); + let data_2 = *result.data[2]; assert(data_2 == 3, 'result[2] == 3'); - let data_3 = *result.data.at(3); + let data_3 = *result.data[3]; assert(data_3 == 4, 'result[3] == 4'); } } @@ -144,28 +144,28 @@ mod input_3D { let threshold = 3; let mut result = NNTrait::relu(@tensor, threshold); - let data_0 = *result.data.at(0); + let data_0 = *result.data[0]; assert(data_0 == 0, 'result[0] == 0'); - let data_1 = *result.data.at(1); + let data_1 = *result.data[1]; assert(data_1 == 0, 'result[1] == 0'); - let data_2 = *result.data.at(2); + let data_2 = *result.data[2]; assert(data_2 == 3, 'result[2] == 3'); - let data_3 = *result.data.at(3); + let data_3 = *result.data[3]; assert(data_3 == 4, 'result[3] == 4'); - let data_4 = *result.data.at(4); + let data_4 = *result.data[4]; assert(data_4 == 5, 'result[4] == 5'); - let data_5 = *result.data.at(5); + let data_5 = *result.data[5]; assert(data_5 == 6, 'result[5] == 6'); - let data_6 = *result.data.at(6); + let data_6 = *result.data[6]; assert(data_6 == 7, 'result[6] == 7'); - let data_7 = *result.data.at(7); + let data_7 = *result.data[7]; assert(data_7 == 8, 'result[7] == 8'); } } diff --git a/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo index 2a9306462..1d935c5dd 100644 --- a/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo +++ b/src/tests/operators/nn/functional/softmax/softmax_i32_test.cairo @@ -27,9 +27,9 @@ mod input_1D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 755231, 'result[0] = 0.09003057'); - assert((*result.at(1)).into() == 2052931, 'result[1] = 0.24472847'); - assert((*result.at(2)).into() == 5580445, 'result[2] = 0.66524096'); + assert((*result[0]).into() == 755231, 'result[0] = 0.09003057'); + assert((*result[1]).into() == 2052931, 'result[1] = 0.24472847'); + assert((*result[2]).into() == 5580445, 'result[2] = 0.66524096'); } } @@ -58,9 +58,9 @@ mod input_1D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 5900, 'result[0] = 0.09003057'); - assert((*result.at(1)).into() == 16038, 'result[1] = 0.24472847'); - assert((*result.at(2)).into() == 43596, 'result[2] = 0.66524096'); + assert((*result[0]).into() == 5900, 'result[0] = 0.09003057'); + assert((*result[1]).into() == 16038, 'result[1] = 0.24472847'); + assert((*result[2]).into() == 43596, 'result[2] = 0.66524096'); } } } @@ -91,17 +91,17 @@ mod input_2D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 999946, 'result[0] = 0.1192'); - assert((*result.at(1)).into() == 999946, 'result[1] = 0.1192'); - assert((*result.at(2)).into() == 7388661, 'result[2] = 0.8808'); - assert((*result.at(3)).into() == 7388661, 'result[3] = 0.8808'); + assert((*result[0]).into() == 999946, 'result[0] = 0.1192'); + assert((*result[1]).into() == 999946, 'result[1] = 0.1192'); + assert((*result[2]).into() == 7388661, 'result[2] = 0.8808'); + assert((*result[3]).into() == 7388661, 'result[3] = 0.8808'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert((*result.at(0)).into() == 2256044, 'result[0] = 0.2689'); - assert((*result.at(1)).into() == 6132563, 'result[1] = 0.7311'); - assert((*result.at(2)).into() == 2256043, 'result[2] = 0.2689'); - assert((*result.at(3)).into() == 6132564, 'result[4] = 0.7311'); + assert((*result[0]).into() == 2256044, 'result[0] = 0.2689'); + assert((*result[1]).into() == 6132563, 'result[1] = 0.7311'); + assert((*result[2]).into() == 2256043, 'result[2] = 0.2689'); + assert((*result[3]).into() == 6132564, 'result[4] = 0.7311'); } } @@ -130,17 +130,17 @@ mod input_2D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 7812, 'result[0] = 0.1192'); - assert((*result.at(1)).into() == 7812, 'result[1] = 0.1192'); - assert((*result.at(2)).into() == 57723, 'result[2] = 0.8808'); - assert((*result.at(3)).into() == 57723, 'result[3] = 0.8808'); + assert((*result[0]).into() == 7812, 'result[0] = 0.1192'); + assert((*result[1]).into() == 7812, 'result[1] = 0.1192'); + assert((*result[2]).into() == 57723, 'result[2] = 0.8808'); + assert((*result[3]).into() == 57723, 'result[3] = 0.8808'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert((*result.at(0)).into() == 17625, 'result[0] = 0.2689'); - assert((*result.at(1)).into() == 47910, 'result[1] = 0.7311'); - assert((*result.at(2)).into() == 17625, 'result[2] = 0.2689'); - assert((*result.at(3)).into() == 47910, 'result[4] = 0.7311'); + assert((*result[0]).into() == 17625, 'result[0] = 0.2689'); + assert((*result[1]).into() == 47910, 'result[1] = 0.7311'); + assert((*result[2]).into() == 17625, 'result[2] = 0.2689'); + assert((*result[3]).into() == 47910, 'result[4] = 0.7311'); } } } @@ -174,36 +174,36 @@ mod input_3D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 150879, 'result[0] = 0.01798621'); - assert((*result.at(1)).into() == 150879, 'result[1] = 0.01798621'); - assert((*result.at(2)).into() == 150879, 'result[2] = 0.01798621'); - assert((*result.at(3)).into() == 150879, 'result[3] = 0.01798621'); - assert((*result.at(4)).into() == 8237728, 'result[4] = 0.01798621'); - assert((*result.at(5)).into() == 8237728, 'result[5] = 0.01798621'); - assert((*result.at(6)).into() == 8237728, 'result[6] = 0.01798621'); - assert((*result.at(7)).into() == 8237728, 'result[7] = 0.01798621'); + assert((*result[0]).into() == 150879, 'result[0] = 0.01798621'); + assert((*result[1]).into() == 150879, 'result[1] = 0.01798621'); + assert((*result[2]).into() == 150879, 'result[2] = 0.01798621'); + assert((*result[3]).into() == 150879, 'result[3] = 0.01798621'); + assert((*result[4]).into() == 8237728, 'result[4] = 0.01798621'); + assert((*result[5]).into() == 8237728, 'result[5] = 0.01798621'); + assert((*result[6]).into() == 8237728, 'result[6] = 0.01798621'); + assert((*result[7]).into() == 8237728, 'result[7] = 0.01798621'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert((*result.at(0)).into() == 999946, 'result[0] = 0.11920292'); - assert((*result.at(1)).into() == 999946, 'result[1] = 0.11920292'); - assert((*result.at(2)).into() == 7388661, 'result[2] = 0.88079708'); - assert((*result.at(3)).into() == 7388661, 'result[3] = 0.88079708'); - assert((*result.at(4)).into() == 999946, 'result[4] = 0.11920292'); - assert((*result.at(5)).into() == 999946, 'result[5] = 0.11920292'); - assert((*result.at(6)).into() == 7388661, 'result[6] = 0.88079708'); - assert((*result.at(7)).into() == 7388661, 'result[7] = 0.88079708'); + assert((*result[0]).into() == 999946, 'result[0] = 0.11920292'); + assert((*result[1]).into() == 999946, 'result[1] = 0.11920292'); + assert((*result[2]).into() == 7388661, 'result[2] = 0.88079708'); + assert((*result[3]).into() == 7388661, 'result[3] = 0.88079708'); + assert((*result[4]).into() == 999946, 'result[4] = 0.11920292'); + assert((*result[5]).into() == 999946, 'result[5] = 0.11920292'); + assert((*result[6]).into() == 7388661, 'result[6] = 0.88079708'); + assert((*result[7]).into() == 7388661, 'result[7] = 0.88079708'); let mut result = NNTrait::softmax(@tensor, 2).data; - assert((*result.at(0)).into() == 2256044, 'result[0] = 0.26894142'); - assert((*result.at(1)).into() == 6132563, 'result[1] = 0.73105858'); - assert((*result.at(2)).into() == 2256043, 'result[2] = 0.26894142'); - assert((*result.at(3)).into() == 6132564, 'result[3] = 0.73105858'); - assert((*result.at(4)).into() == 2256044, 'result[4] = 0.26894142'); - assert((*result.at(5)).into() == 6132563, 'result[5] = 0.73105858'); - assert((*result.at(6)).into() == 2256044, 'result[6] = 0.26894142'); - assert((*result.at(7)).into() == 6132563, 'result[7] = 0.73105858'); + assert((*result[0]).into() == 2256044, 'result[0] = 0.26894142'); + assert((*result[1]).into() == 6132563, 'result[1] = 0.73105858'); + assert((*result[2]).into() == 2256043, 'result[2] = 0.26894142'); + assert((*result[3]).into() == 6132564, 'result[3] = 0.73105858'); + assert((*result[4]).into() == 2256044, 'result[4] = 0.26894142'); + assert((*result[5]).into() == 6132563, 'result[5] = 0.73105858'); + assert((*result[6]).into() == 2256044, 'result[6] = 0.26894142'); + assert((*result[7]).into() == 6132563, 'result[7] = 0.73105858'); } } @@ -232,36 +232,36 @@ mod input_3D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 1178, 'result[0] = 0.01798621'); - assert((*result.at(1)).into() == 1178, 'result[1] = 0.01798621'); - assert((*result.at(2)).into() == 1178, 'result[2] = 0.01798621'); - assert((*result.at(3)).into() == 1178, 'result[3] = 0.01798621'); - assert((*result.at(4)).into() == 64357, 'result[4] = 0.01798621'); - assert((*result.at(5)).into() == 64357, 'result[5] = 0.01798621'); - assert((*result.at(6)).into() == 64357, 'result[6] = 0.01798621'); - assert((*result.at(7)).into() == 64357, 'result[7] = 0.01798621'); + assert((*result[0]).into() == 1178, 'result[0] = 0.01798621'); + assert((*result[1]).into() == 1178, 'result[1] = 0.01798621'); + assert((*result[2]).into() == 1178, 'result[2] = 0.01798621'); + assert((*result[3]).into() == 1178, 'result[3] = 0.01798621'); + assert((*result[4]).into() == 64357, 'result[4] = 0.01798621'); + assert((*result[5]).into() == 64357, 'result[5] = 0.01798621'); + assert((*result[6]).into() == 64357, 'result[6] = 0.01798621'); + assert((*result[7]).into() == 64357, 'result[7] = 0.01798621'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert((*result.at(0)).into() == 7812, 'result[0] = 0.11920292'); - assert((*result.at(1)).into() == 7812, 'result[1] = 0.11920292'); - assert((*result.at(2)).into() == 57723, 'result[2] = 0.88079708'); - assert((*result.at(3)).into() == 57723, 'result[3] = 0.88079708'); - assert((*result.at(4)).into() == 7812, 'result[4] = 0.11920292'); - assert((*result.at(5)).into() == 7812, 'result[5] = 0.11920292'); - assert((*result.at(6)).into() == 57723, 'result[6] = 0.88079708'); - assert((*result.at(7)).into() == 57723, 'result[7] = 0.88079708'); + assert((*result[0]).into() == 7812, 'result[0] = 0.11920292'); + assert((*result[1]).into() == 7812, 'result[1] = 0.11920292'); + assert((*result[2]).into() == 57723, 'result[2] = 0.88079708'); + assert((*result[3]).into() == 57723, 'result[3] = 0.88079708'); + assert((*result[4]).into() == 7812, 'result[4] = 0.11920292'); + assert((*result[5]).into() == 7812, 'result[5] = 0.11920292'); + assert((*result[6]).into() == 57723, 'result[6] = 0.88079708'); + assert((*result[7]).into() == 57723, 'result[7] = 0.88079708'); let mut result = NNTrait::softmax(@tensor, 2).data; - assert((*result.at(0)).into() == 17625, 'result[0] = 0.26894142'); - assert((*result.at(1)).into() == 47910, 'result[1] = 0.73105858'); - assert((*result.at(2)).into() == 17625, 'result[2] = 0.26894142'); - assert((*result.at(3)).into() == 47910, 'result[3] = 0.73105858'); - assert((*result.at(4)).into() == 17625, 'result[4] = 0.26894142'); - assert((*result.at(5)).into() == 47910, 'result[5] = 0.73105858'); - assert((*result.at(6)).into() == 17625, 'result[6] = 0.26894142'); - assert((*result.at(7)).into() == 47910, 'result[7] = 0.73105858'); + assert((*result[0]).into() == 17625, 'result[0] = 0.26894142'); + assert((*result[1]).into() == 47910, 'result[1] = 0.73105858'); + assert((*result[2]).into() == 17625, 'result[2] = 0.26894142'); + assert((*result[3]).into() == 47910, 'result[3] = 0.73105858'); + assert((*result[4]).into() == 17625, 'result[4] = 0.26894142'); + assert((*result[5]).into() == 47910, 'result[5] = 0.73105858'); + assert((*result[6]).into() == 17625, 'result[6] = 0.26894142'); + assert((*result[7]).into() == 47910, 'result[7] = 0.73105858'); } } } diff --git a/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo b/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo index 39d9daeb2..f91ffa555 100644 --- a/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo +++ b/src/tests/operators/nn/functional/softmax/softmax_u32_test.cairo @@ -27,9 +27,9 @@ mod input_1D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 755231, 'result[0] = 0.09003057'); - assert((*result.at(1)).into() == 2052931, 'result[1] = 0.24472847'); - assert((*result.at(2)).into() == 5580445, 'result[2] = 0.66524096'); + assert((*result[0]).into() == 755231, 'result[0] = 0.09003057'); + assert((*result[1]).into() == 2052931, 'result[1] = 0.24472847'); + assert((*result[2]).into() == 5580445, 'result[2] = 0.66524096'); } } @@ -58,9 +58,9 @@ mod input_1D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 5900, 'result[0] = 0.09003057'); - assert((*result.at(1)).into() == 16038, 'result[1] = 0.24472847'); - assert((*result.at(2)).into() == 43596, 'result[2] = 0.66524096'); + assert((*result[0]).into() == 5900, 'result[0] = 0.09003057'); + assert((*result[1]).into() == 16038, 'result[1] = 0.24472847'); + assert((*result[2]).into() == 43596, 'result[2] = 0.66524096'); } } } @@ -91,17 +91,17 @@ mod input_2D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 999946, 'result[0] = 0.1192'); - assert((*result.at(1)).into() == 999946, 'result[1] = 0.1192'); - assert((*result.at(2)).into() == 7388661, 'result[2] = 0.8808'); - assert((*result.at(3)).into() == 7388661, 'result[3] = 0.8808'); + assert((*result[0]).into() == 999946, 'result[0] = 0.1192'); + assert((*result[1]).into() == 999946, 'result[1] = 0.1192'); + assert((*result[2]).into() == 7388661, 'result[2] = 0.8808'); + assert((*result[3]).into() == 7388661, 'result[3] = 0.8808'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert((*result.at(0)).into() == 2256044, 'result[0] = 0.2689'); - assert((*result.at(1)).into() == 6132563, 'result[1] = 0.7311'); - assert((*result.at(2)).into() == 2256043, 'result[2] = 0.2689'); - assert((*result.at(3)).into() == 6132564, 'result[4] = 0.7311'); + assert((*result[0]).into() == 2256044, 'result[0] = 0.2689'); + assert((*result[1]).into() == 6132563, 'result[1] = 0.7311'); + assert((*result[2]).into() == 2256043, 'result[2] = 0.2689'); + assert((*result[3]).into() == 6132564, 'result[4] = 0.7311'); } } @@ -130,17 +130,17 @@ mod input_2D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 7812, 'result[0] = 0.1192'); - assert((*result.at(1)).into() == 7812, 'result[1] = 0.1192'); - assert((*result.at(2)).into() == 57723, 'result[2] = 0.8808'); - assert((*result.at(3)).into() == 57723, 'result[3] = 0.8808'); + assert((*result[0]).into() == 7812, 'result[0] = 0.1192'); + assert((*result[1]).into() == 7812, 'result[1] = 0.1192'); + assert((*result[2]).into() == 57723, 'result[2] = 0.8808'); + assert((*result[3]).into() == 57723, 'result[3] = 0.8808'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert((*result.at(0)).into() == 17625, 'result[0] = 0.2689'); - assert((*result.at(1)).into() == 47910, 'result[1] = 0.7311'); - assert((*result.at(2)).into() == 17625, 'result[2] = 0.2689'); - assert((*result.at(3)).into() == 47910, 'result[4] = 0.7311'); + assert((*result[0]).into() == 17625, 'result[0] = 0.2689'); + assert((*result[1]).into() == 47910, 'result[1] = 0.7311'); + assert((*result[2]).into() == 17625, 'result[2] = 0.2689'); + assert((*result[3]).into() == 47910, 'result[4] = 0.7311'); } } } @@ -174,36 +174,36 @@ mod input_3D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 150879, 'result[0] = 0.01798621'); - assert((*result.at(1)).into() == 150879, 'result[1] = 0.01798621'); - assert((*result.at(2)).into() == 150879, 'result[2] = 0.01798621'); - assert((*result.at(3)).into() == 150879, 'result[3] = 0.01798621'); - assert((*result.at(4)).into() == 8237728, 'result[4] = 0.01798621'); - assert((*result.at(5)).into() == 8237728, 'result[5] = 0.01798621'); - assert((*result.at(6)).into() == 8237728, 'result[6] = 0.01798621'); - assert((*result.at(7)).into() == 8237728, 'result[7] = 0.01798621'); + assert((*result[0]).into() == 150879, 'result[0] = 0.01798621'); + assert((*result[1]).into() == 150879, 'result[1] = 0.01798621'); + assert((*result[2]).into() == 150879, 'result[2] = 0.01798621'); + assert((*result[3]).into() == 150879, 'result[3] = 0.01798621'); + assert((*result[4]).into() == 8237728, 'result[4] = 0.01798621'); + assert((*result[5]).into() == 8237728, 'result[5] = 0.01798621'); + assert((*result[6]).into() == 8237728, 'result[6] = 0.01798621'); + assert((*result[7]).into() == 8237728, 'result[7] = 0.01798621'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert((*result.at(0)).into() == 999946, 'result[0] = 0.11920292'); - assert((*result.at(1)).into() == 999946, 'result[1] = 0.11920292'); - assert((*result.at(2)).into() == 7388661, 'result[2] = 0.88079708'); - assert((*result.at(3)).into() == 7388661, 'result[3] = 0.88079708'); - assert((*result.at(4)).into() == 999946, 'result[4] = 0.11920292'); - assert((*result.at(5)).into() == 999946, 'result[5] = 0.11920292'); - assert((*result.at(6)).into() == 7388661, 'result[6] = 0.88079708'); - assert((*result.at(7)).into() == 7388661, 'result[7] = 0.88079708'); + assert((*result[0]).into() == 999946, 'result[0] = 0.11920292'); + assert((*result[1]).into() == 999946, 'result[1] = 0.11920292'); + assert((*result[2]).into() == 7388661, 'result[2] = 0.88079708'); + assert((*result[3]).into() == 7388661, 'result[3] = 0.88079708'); + assert((*result[4]).into() == 999946, 'result[4] = 0.11920292'); + assert((*result[5]).into() == 999946, 'result[5] = 0.11920292'); + assert((*result[6]).into() == 7388661, 'result[6] = 0.88079708'); + assert((*result[7]).into() == 7388661, 'result[7] = 0.88079708'); let mut result = NNTrait::softmax(@tensor, 2).data; - assert((*result.at(0)).into() == 2256044, 'result[0] = 0.26894142'); - assert((*result.at(1)).into() == 6132563, 'result[1] = 0.73105858'); - assert((*result.at(2)).into() == 2256043, 'result[2] = 0.26894142'); - assert((*result.at(3)).into() == 6132564, 'result[3] = 0.73105858'); - assert((*result.at(4)).into() == 2256044, 'result[4] = 0.26894142'); - assert((*result.at(5)).into() == 6132563, 'result[5] = 0.73105858'); - assert((*result.at(6)).into() == 2256044, 'result[6] = 0.26894142'); - assert((*result.at(7)).into() == 6132563, 'result[7] = 0.73105858'); + assert((*result[0]).into() == 2256044, 'result[0] = 0.26894142'); + assert((*result[1]).into() == 6132563, 'result[1] = 0.73105858'); + assert((*result[2]).into() == 2256043, 'result[2] = 0.26894142'); + assert((*result[3]).into() == 6132564, 'result[3] = 0.73105858'); + assert((*result[4]).into() == 2256044, 'result[4] = 0.26894142'); + assert((*result[5]).into() == 6132563, 'result[5] = 0.73105858'); + assert((*result[6]).into() == 2256044, 'result[6] = 0.26894142'); + assert((*result[7]).into() == 6132563, 'result[7] = 0.73105858'); } } @@ -232,36 +232,36 @@ mod input_3D { let mut result = NNTrait::softmax(@tensor, 0).data; - assert((*result.at(0)).into() == 1178, 'result[0] = 0.01798621'); - assert((*result.at(1)).into() == 1178, 'result[1] = 0.01798621'); - assert((*result.at(2)).into() == 1178, 'result[2] = 0.01798621'); - assert((*result.at(3)).into() == 1178, 'result[3] = 0.01798621'); - assert((*result.at(4)).into() == 64357, 'result[4] = 0.01798621'); - assert((*result.at(5)).into() == 64357, 'result[5] = 0.01798621'); - assert((*result.at(6)).into() == 64357, 'result[6] = 0.01798621'); - assert((*result.at(7)).into() == 64357, 'result[7] = 0.01798621'); + assert((*result[0]).into() == 1178, 'result[0] = 0.01798621'); + assert((*result[1]).into() == 1178, 'result[1] = 0.01798621'); + assert((*result[2]).into() == 1178, 'result[2] = 0.01798621'); + assert((*result[3]).into() == 1178, 'result[3] = 0.01798621'); + assert((*result[4]).into() == 64357, 'result[4] = 0.01798621'); + assert((*result[5]).into() == 64357, 'result[5] = 0.01798621'); + assert((*result[6]).into() == 64357, 'result[6] = 0.01798621'); + assert((*result[7]).into() == 64357, 'result[7] = 0.01798621'); let mut result = NNTrait::softmax(@tensor, 1).data; - assert((*result.at(0)).into() == 7812, 'result[0] = 0.11920292'); - assert((*result.at(1)).into() == 7812, 'result[1] = 0.11920292'); - assert((*result.at(2)).into() == 57723, 'result[2] = 0.88079708'); - assert((*result.at(3)).into() == 57723, 'result[3] = 0.88079708'); - assert((*result.at(4)).into() == 7812, 'result[4] = 0.11920292'); - assert((*result.at(5)).into() == 7812, 'result[5] = 0.11920292'); - assert((*result.at(6)).into() == 57723, 'result[6] = 0.88079708'); - assert((*result.at(7)).into() == 57723, 'result[7] = 0.88079708'); + assert((*result[0]).into() == 7812, 'result[0] = 0.11920292'); + assert((*result[1]).into() == 7812, 'result[1] = 0.11920292'); + assert((*result[2]).into() == 57723, 'result[2] = 0.88079708'); + assert((*result[3]).into() == 57723, 'result[3] = 0.88079708'); + assert((*result[4]).into() == 7812, 'result[4] = 0.11920292'); + assert((*result[5]).into() == 7812, 'result[5] = 0.11920292'); + assert((*result[6]).into() == 57723, 'result[6] = 0.88079708'); + assert((*result[7]).into() == 57723, 'result[7] = 0.88079708'); let mut result = NNTrait::softmax(@tensor, 2).data; - assert((*result.at(0)).into() == 17625, 'result[0] = 0.26894142'); - assert((*result.at(1)).into() == 47910, 'result[1] = 0.73105858'); - assert((*result.at(2)).into() == 17625, 'result[2] = 0.26894142'); - assert((*result.at(3)).into() == 47910, 'result[3] = 0.73105858'); - assert((*result.at(4)).into() == 17625, 'result[4] = 0.26894142'); - assert((*result.at(5)).into() == 47910, 'result[5] = 0.73105858'); - assert((*result.at(6)).into() == 17625, 'result[6] = 0.26894142'); - assert((*result.at(7)).into() == 47910, 'result[7] = 0.73105858'); + assert((*result[0]).into() == 17625, 'result[0] = 0.26894142'); + assert((*result[1]).into() == 47910, 'result[1] = 0.73105858'); + assert((*result[2]).into() == 17625, 'result[2] = 0.26894142'); + assert((*result[3]).into() == 47910, 'result[3] = 0.73105858'); + assert((*result[4]).into() == 17625, 'result[4] = 0.26894142'); + assert((*result[5]).into() == 47910, 'result[5] = 0.73105858'); + assert((*result[6]).into() == 17625, 'result[6] = 0.26894142'); + assert((*result[7]).into() == 47910, 'result[7] = 0.73105858'); } } } diff --git a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo index 82f33ae41..1b04ec603 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_i32_test.cairo @@ -38,10 +38,10 @@ mod input_1D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 - assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 - assert((*result.data.at(2)).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 - assert((*result.data.at(3)).into() == 407580, 'result[3] == 407580'); // 0.04858729 + assert((*result.data[0]).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data[1]).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data[2]).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 + assert((*result.data[3]).into() == 407580, 'result[3] == 407580'); // 0.04858729 } } @@ -84,10 +84,10 @@ mod input_1D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 - assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 - assert((*result.data.at(2)).into() == 8315, 'result[2] == 8315'); // 0.12692797 - assert((*result.data.at(3)).into() == 3182, 'result[3] == 3182'); // 0.04858729 + assert((*result.data[0]).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data[1]).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data[2]).into() == 8315, 'result[2] == 8315'); // 0.12692797 + assert((*result.data[3]).into() == 3182, 'result[3] == 3182'); // 0.04858729 } } } @@ -133,10 +133,10 @@ mod input_2D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 - assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 - assert((*result.data.at(2)).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 - assert((*result.data.at(3)).into() == 407580, 'result[3] == 407580'); // 0.04858729 + assert((*result.data[0]).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data[1]).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data[2]).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 + assert((*result.data[3]).into() == 407580, 'result[3] == 407580'); // 0.04858729 } } @@ -180,10 +180,10 @@ mod input_2D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 - assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 - assert((*result.data.at(2)).into() == 8315, 'result[2] == 8315'); // 0.12692797 - assert((*result.data.at(3)).into() == 3182, 'result[3] == 3182'); // 0.04858729 + assert((*result.data[0]).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data[1]).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data[2]).into() == 8315, 'result[2] == 8315'); // 0.12692797 + assert((*result.data[3]).into() == 3182, 'result[3] == 3182'); // 0.04858729 } } } @@ -238,14 +238,14 @@ mod input_3D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 - assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 - assert((*result.data.at(2)).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 - assert((*result.data.at(3)).into() == 407580, 'result[3] == 407580'); // 0.04858729 - assert((*result.data.at(4)).into() == 5814556, 'result[4] == 5814556'); // 0.6931452 - assert((*result.data.at(5)).into() == 11016447, 'result[5] == 11016447'); // 1.31326096 - assert((*result.data.at(6)).into() == 1064751, 'result[6] == 1064751'); // 0.12692797 - assert((*result.data.at(7)).into() == 407580, 'result[7] == 407580'); // 0.04858729 + assert((*result.data[0]).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data[1]).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data[2]).into() == 1064751, 'result[2] == 1064751'); // 0.12692797 + assert((*result.data[3]).into() == 407580, 'result[3] == 407580'); // 0.04858729 + assert((*result.data[4]).into() == 5814556, 'result[4] == 5814556'); // 0.6931452 + assert((*result.data[5]).into() == 11016447, 'result[5] == 11016447'); // 1.31326096 + assert((*result.data[6]).into() == 1064751, 'result[6] == 1064751'); // 0.12692797 + assert((*result.data[7]).into() == 407580, 'result[7] == 407580'); // 0.04858729 } } @@ -298,14 +298,14 @@ mod input_3D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 - assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 - assert((*result.data.at(2)).into() == 8315, 'result[2] == 8315'); // 0.12692797 - assert((*result.data.at(3)).into() == 3182, 'result[3] == 3182'); // 0.04858729 - assert((*result.data.at(4)).into() == 45355, 'result[4] == 45355'); // 0.6931452 - assert((*result.data.at(5)).into() == 86022, 'result[5] == 86022'); // 1.31326096 - assert((*result.data.at(6)).into() == 8315, 'result[6] == 8315'); // 0.12692797 - assert((*result.data.at(7)).into() == 3182, 'result[7] == 3182'); // 0.04858729 + assert((*result.data[0]).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data[1]).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data[2]).into() == 8315, 'result[2] == 8315'); // 0.12692797 + assert((*result.data[3]).into() == 3182, 'result[3] == 3182'); // 0.04858729 + assert((*result.data[4]).into() == 45355, 'result[4] == 45355'); // 0.6931452 + assert((*result.data[5]).into() == 86022, 'result[5] == 86022'); // 1.31326096 + assert((*result.data[6]).into() == 8315, 'result[6] == 8315'); // 0.12692797 + assert((*result.data[7]).into() == 3182, 'result[7] == 3182'); // 0.04858729 } } } diff --git a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo index ac3c2c0f1..046297248 100644 --- a/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo +++ b/src/tests/operators/nn/functional/softplus/softplus_u32_test.cairo @@ -37,10 +37,10 @@ mod input_1D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 - assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 - assert((*result.data.at(2)).into() == 17841964, 'result[2] == 17841964'); // 2.1269 - assert((*result.data.at(3)).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 + assert((*result.data[0]).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data[1]).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data[2]).into() == 17841964, 'result[2] == 17841964'); // 2.1269 + assert((*result.data[3]).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 } } @@ -79,12 +79,12 @@ mod input_1D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 - assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data[0]).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data[1]).into() == 86022, 'result[1] == 86022'); // 1.31326096 assert( - (*result.data.at(2)).into() == 139388, 'result[2] == 139388' + (*result.data[2]).into() == 139388, 'result[2] == 139388' ); // 2.12689208984375 - assert((*result.data.at(3)).into() == 199788, 'result[3] == 199788'); // 3.04852294 + assert((*result.data[3]).into() == 199788, 'result[3] == 199788'); // 3.04852294 } } } @@ -129,12 +129,12 @@ mod input_2D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 - assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data[0]).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data[1]).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 assert( - (*result.data.at(2)).into() == 17841964, 'result[2] == 17841964' + (*result.data[2]).into() == 17841964, 'result[2] == 17841964' ); // 2.12689208984375 - assert((*result.data.at(3)).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 + assert((*result.data[3]).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 } } @@ -174,12 +174,12 @@ mod input_2D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 - assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data[0]).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data[1]).into() == 86022, 'result[1] == 86022'); // 1.31326096 assert( - (*result.data.at(2)).into() == 139388, 'result[2] == 139388' + (*result.data[2]).into() == 139388, 'result[2] == 139388' ); // 2.12689208984375 - assert((*result.data.at(3)).into() == 199788, 'result[3] == 199788'); // 3.04852294 + assert((*result.data[3]).into() == 199788, 'result[3] == 199788'); // 3.04852294 } } } @@ -233,16 +233,16 @@ mod input_3D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 - assert((*result.data.at(1)).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 + assert((*result.data[0]).into() == 5814556, 'result[0] == 5814556'); // 0.6931452 + assert((*result.data[1]).into() == 11016447, 'result[1] == 11016447'); // 1.31326096 assert( - (*result.data.at(2)).into() == 17841964, 'result[2] == 17841964' + (*result.data[2]).into() == 17841964, 'result[2] == 17841964' ); // 2.12689208984375 - assert((*result.data.at(3)).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 - assert((*result.data.at(4)).into() == 5814556, 'result[4] == 5814556'); // 0.6931452 - assert((*result.data.at(5)).into() == 11016447, 'result[5] == 11016447'); // 1.31326096 - assert((*result.data.at(6)).into() == 17841964, 'result[6] == 17841964'); // 2.1269278 - assert((*result.data.at(7)).into() == 25573406, 'result[7] == 25573406'); // 3.0485875 + assert((*result.data[3]).into() == 25573406, 'result[3] == 25573406'); // 3.0485875 + assert((*result.data[4]).into() == 5814556, 'result[4] == 5814556'); // 0.6931452 + assert((*result.data[5]).into() == 11016447, 'result[5] == 11016447'); // 1.31326096 + assert((*result.data[6]).into() == 17841964, 'result[6] == 17841964'); // 2.1269278 + assert((*result.data[7]).into() == 25573406, 'result[7] == 25573406'); // 3.0485875 } } @@ -291,18 +291,18 @@ mod input_3D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softplus(@tensor); - assert((*result.data.at(0)).into() == 45355, 'result[0] == 45355'); // 0.6931452 - assert((*result.data.at(1)).into() == 86022, 'result[1] == 86022'); // 1.31326096 + assert((*result.data[0]).into() == 45355, 'result[0] == 45355'); // 0.6931452 + assert((*result.data[1]).into() == 86022, 'result[1] == 86022'); // 1.31326096 assert( - (*result.data.at(2)).into() == 139388, 'result[2] == 139388' + (*result.data[2]).into() == 139388, 'result[2] == 139388' ); // 2.12689208984375 - assert((*result.data.at(3)).into() == 199788, 'result[3] == 199788'); // 3.04852294 - assert((*result.data.at(4)).into() == 45355, 'result[4] == 45355'); // 0.6931452 - assert((*result.data.at(5)).into() == 86022, 'result[5] == 86022'); // 1.31326096 + assert((*result.data[3]).into() == 199788, 'result[3] == 199788'); // 3.04852294 + assert((*result.data[4]).into() == 45355, 'result[4] == 45355'); // 0.6931452 + assert((*result.data[5]).into() == 86022, 'result[5] == 86022'); // 1.31326096 assert( - (*result.data.at(6)).into() == 139388, 'result[6] == 139388' + (*result.data[6]).into() == 139388, 'result[6] == 139388' ); // 2.12689208984375 - assert((*result.data.at(7)).into() == 199788, 'result[7] == 199788'); // 3.04852294 + assert((*result.data[7]).into() == 199788, 'result[7] == 199788'); // 3.04852294 } } } diff --git a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo index e19c1283d..dc85e4a87 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_i32_test.cairo @@ -39,10 +39,10 @@ mod input_1D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 - assert((*result.data.at(1)).into() == 4194304, 'result[1] == 4194304'); // 0.5 - assert((*result.data.at(2)).into() == -5592405, 'result[2] == 5592405'); // -0.67 - assert((*result.data.at(3)).into() == -6291456, 'result[3] == 6291456'); // -0.75 + assert((*result.data[0]).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data[1]).into() == 4194304, 'result[1] == 4194304'); // 0.5 + assert((*result.data[2]).into() == -5592405, 'result[2] == 5592405'); // -0.67 + assert((*result.data[3]).into() == -6291456, 'result[3] == 6291456'); // -0.75 } } @@ -82,10 +82,10 @@ mod input_1D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 - assert((*result.data.at(1)).into() == 32768, 'result[1] == 32768'); // 0.5 - assert((*result.data.at(2)).into() == -43690, 'result[2] == 43690'); // -0.67 - assert((*result.data.at(3)).into() == -49152, 'result[3] == 49152'); // -0.75 + assert((*result.data[0]).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data[1]).into() == 32768, 'result[1] == 32768'); // 0.5 + assert((*result.data[2]).into() == -43690, 'result[2] == 43690'); // -0.67 + assert((*result.data[3]).into() == -49152, 'result[3] == 49152'); // -0.75 } } } @@ -133,10 +133,10 @@ mod input_2D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 - assert((*result.data.at(1)).into() == 4194304, 'result[1] == 4194304'); // 0.5 - assert((*result.data.at(2)).into() == -5592405, 'result[2] == 5592405'); // -0.67 - assert((*result.data.at(3)).into() == -6291456, 'result[3] == 6291456'); // -0.75 + assert((*result.data[0]).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data[1]).into() == 4194304, 'result[1] == 4194304'); // 0.5 + assert((*result.data[2]).into() == -5592405, 'result[2] == 5592405'); // -0.67 + assert((*result.data[3]).into() == -6291456, 'result[3] == 6291456'); // -0.75 } } @@ -177,10 +177,10 @@ mod input_2D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 - assert((*result.data.at(1)).into() == 32768, 'result[1] == 32768'); // 0.5 - assert((*result.data.at(2)).into() == -43690, 'result[2] == 43690'); // -0.67 - assert((*result.data.at(3)).into() == -49152, 'result[3] == 49152'); // -0.75 + assert((*result.data[0]).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data[1]).into() == 32768, 'result[1] == 32768'); // 0.5 + assert((*result.data[2]).into() == -43690, 'result[2] == 43690'); // -0.67 + assert((*result.data[3]).into() == -49152, 'result[3] == 49152'); // -0.75 } } } @@ -236,14 +236,14 @@ mod input_3D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 - assert((*result.data.at(1)).into() == 4194304, 'result[1] == 4194304'); // 0.5 - assert((*result.data.at(2)).into() == -5592405, 'result[2] == 5592405'); // -0.67 - assert((*result.data.at(3)).into() == -6291456, 'result[3] == 6291456'); // -0.75 - assert((*result.data.at(4)).into() == 0, 'result[4] == 0'); // 0 - assert((*result.data.at(5)).into() == 4194304, 'result[5] == 4194304'); // 0.5 - assert((*result.data.at(6)).into() == -5592405, 'result[6] == 5592405'); // -0.67 - assert((*result.data.at(7)).into() == -6291456, 'result[7] == 6291456'); // -0.75 + assert((*result.data[0]).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data[1]).into() == 4194304, 'result[1] == 4194304'); // 0.5 + assert((*result.data[2]).into() == -5592405, 'result[2] == 5592405'); // -0.67 + assert((*result.data[3]).into() == -6291456, 'result[3] == 6291456'); // -0.75 + assert((*result.data[4]).into() == 0, 'result[4] == 0'); // 0 + assert((*result.data[5]).into() == 4194304, 'result[5] == 4194304'); // 0.5 + assert((*result.data[6]).into() == -5592405, 'result[6] == 5592405'); // -0.67 + assert((*result.data[7]).into() == -6291456, 'result[7] == 6291456'); // -0.75 } } @@ -293,14 +293,14 @@ mod input_3D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - assert((*result.data.at(0)).into() == 0, 'result[0] == 0'); // 0 - assert((*result.data.at(1)).into() == 32768, 'result[1] == 32768'); // 0.5 - assert((*result.data.at(2)).into() == -43690, 'result[2] == 43690'); // -0.67 - assert((*result.data.at(3)).into() == -49152, 'result[3] == 49152'); // -0.75 - assert((*result.data.at(4)).into() == 0, 'result[4] == 0'); // 0 - assert((*result.data.at(5)).into() == 32768, 'result[5] == 32768'); // 0.5 - assert((*result.data.at(6)).into() == -43690, 'result[6] == 43690'); // -0.67 - assert((*result.data.at(7)).into() == -49152, 'result[7] == 49152'); // -0.75 + assert((*result.data[0]).into() == 0, 'result[0] == 0'); // 0 + assert((*result.data[1]).into() == 32768, 'result[1] == 32768'); // 0.5 + assert((*result.data[2]).into() == -43690, 'result[2] == 43690'); // -0.67 + assert((*result.data[3]).into() == -49152, 'result[3] == 49152'); // -0.75 + assert((*result.data[4]).into() == 0, 'result[4] == 0'); // 0 + assert((*result.data[5]).into() == 32768, 'result[5] == 32768'); // 0.5 + assert((*result.data[6]).into() == -43690, 'result[6] == 43690'); // -0.67 + assert((*result.data[7]).into() == -49152, 'result[7] == 49152'); // -0.75 } } } diff --git a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo index 52c5ec550..2c2286516 100644 --- a/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo +++ b/src/tests/operators/nn/functional/softsign/softsign_u32_test.cairo @@ -41,16 +41,16 @@ mod input_1D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(4194304, false), 'result[1] == 4194304'); // 0.5 - let data = *result.data.at(2); + let data = *result.data[2]; assert(data == FixedTrait::new(5592405, false), 'result[2] == 5592405'); // 0.67 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(6291456, false), 'result[3] == 6291456'); // 0.75 } } @@ -96,16 +96,16 @@ mod input_1D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(32768, false), 'result[1] == 32768'); // 0.5 - let data = *result.data.at(2); + let data = *result.data[2]; assert(data == FixedTrait::new(43690, false), 'result[2] == 43690'); // 0.67 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(49152, false), 'result[3] == 49152'); // 0.75 } } @@ -155,16 +155,16 @@ mod input_2D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(4194304, false), 'result[1] == 4194304'); // 0.5 - let data = *result.data.at(2); + let data = *result.data[2]; assert(data == FixedTrait::new(5592405, false), 'result[2] == 5592405'); // 0.67 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(6291456, false), 'result[3] == 6291456'); // 0.75 } } @@ -210,16 +210,16 @@ mod input_2D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(32768, false), 'result[1] == 32768'); // 0.5 - let data = *result.data.at(2); + let data = *result.data[2]; assert(data == FixedTrait::new(43690, false), 'result[2] == 43690'); // 0.67 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(49152, false), 'result[3] == 49152'); // 0.75 } } @@ -278,28 +278,28 @@ mod input_3D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(4194304, false), 'result[1] == 4194304'); // 0.5 - let data = *result.data.at(2); + let data = *result.data[2]; assert(data == FixedTrait::new(5592405, false), 'result[2] == 5592405'); // 0.67 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(6291456, false), 'result[3] == 6291456'); // 0.75 - let data = *result.data.at(4); + let data = *result.data[4]; assert(data == FixedTrait::new(0, false), 'result[4] == 0'); // 0 - let data = *result.data.at(5); + let data = *result.data[5]; assert(data == FixedTrait::new(4194304, false), 'result[5] == 4194304'); // 0.5 - let data = *result.data.at(6); + let data = *result.data[6]; assert(data == FixedTrait::new(5592405, false), 'result[6] == 5592405'); // 0.67 - let data = *result.data.at(7); + let data = *result.data[7]; assert(data == FixedTrait::new(6291456, false), 'result[7] == 6291456'); // 0.75 } } @@ -354,28 +354,28 @@ mod input_3D { let mut tensor = TensorTrait::new(shape.span(), data.span(), Option::Some(extra)); let mut result = NNTrait::softsign(@tensor); - let data = *result.data.at(0); + let data = *result.data[0]; assert(data == FixedTrait::new(0, false), 'result[0] == 0'); // 0 - let data = *result.data.at(1); + let data = *result.data[1]; assert(data == FixedTrait::new(32768, false), 'result[1] == 32768'); // 0.5 - let data = *result.data.at(2); + let data = *result.data[2]; assert(data == FixedTrait::new(43690, false), 'result[2] == 43690'); // 0.67 - let data = *result.data.at(3); + let data = *result.data[3]; assert(data == FixedTrait::new(49152, false), 'result[3] == 49152'); // 0.75 - let data = *result.data.at(4); + let data = *result.data[4]; assert(data == FixedTrait::new(0, false), 'result[4] == 0'); // 0 - let data = *result.data.at(5); + let data = *result.data[5]; assert(data == FixedTrait::new(32768, false), 'result[5] == 32768'); // 0.5 - let data = *result.data.at(6); + let data = *result.data[6]; assert(data == FixedTrait::new(43690, false), 'result[6] == 43690'); // 0.67 - let data = *result.data.at(7); + let data = *result.data[7]; assert(data == FixedTrait::new(49152, false), 'result[7] == 49152'); // 0.75 } } diff --git a/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp16x16_test.cairo b/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp16x16_test.cairo index f1fec401e..e66691132 100644 --- a/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp16x16_test.cairo +++ b/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp16x16_test.cairo @@ -15,7 +15,7 @@ mod tensor_1D { fn tensor_stride() { let tensor = fp_tensor_1x3_helper(); let result = tensor.stride(); - assert(*result.at(0) == 1, 'stride x = 1'); + assert(*result[0] == 1, 'stride x = 1'); assert(result.len() == 1, 'len = 1'); } } @@ -37,8 +37,8 @@ mod tensor_2D { fn tensor_stride() { let tensor = fp_tensor_2x2_helper(); let result = tensor.stride(); - assert(*result.at(0) == 2, 'stride x = 2'); - assert(*result.at(1) == 1, 'stride y = 1'); + assert(*result[0] == 2, 'stride x = 2'); + assert(*result[1] == 1, 'stride y = 1'); assert(result.len() == 2, 'len = 2'); } } @@ -60,9 +60,9 @@ mod tensor_3D { fn tensor_stride() { let tensor = fp_tensor_2x2x2_helper(); let result = tensor.stride(); - assert(*result.at(0) == 4, 'stride x = 4'); - assert(*result.at(1) == 2, 'stride y = 2'); - assert(*result.at(2) == 1, 'stride z = 1'); + assert(*result[0] == 4, 'stride x = 4'); + assert(*result[1] == 2, 'stride y = 2'); + assert(*result[2] == 1, 'stride z = 1'); assert(result.len() == 3, 'len = 3'); } } diff --git a/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp8x23_test.cairo b/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp8x23_test.cairo index a7a7d670a..ad3a1fe44 100644 --- a/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp8x23_test.cairo +++ b/src/tests/operators/tensor/core/stride/stride_fp_test/stride_fp8x23_test.cairo @@ -15,7 +15,7 @@ mod tensor_1D { fn tensor_stride() { let tensor = fp_tensor_1x3_helper(); let result = tensor.stride(); - assert(*result.at(0) == 1, 'stride x = 1'); + assert(*result[0] == 1, 'stride x = 1'); assert(result.len() == 1, 'len = 1'); } } @@ -37,8 +37,8 @@ mod tensor_2D { fn tensor_stride() { let tensor = fp_tensor_2x2_helper(); let result = tensor.stride(); - assert(*result.at(0) == 2, 'stride x = 2'); - assert(*result.at(1) == 1, 'stride y = 1'); + assert(*result[0] == 2, 'stride x = 2'); + assert(*result[1] == 1, 'stride y = 1'); assert(result.len() == 2, 'len = 2'); } } @@ -60,9 +60,9 @@ mod tensor_3D { fn tensor_stride() { let tensor = fp_tensor_2x2x2_helper(); let result = tensor.stride(); - assert(*result.at(0) == 4, 'stride x = 4'); - assert(*result.at(1) == 2, 'stride y = 2'); - assert(*result.at(2) == 1, 'stride z = 1'); + assert(*result[0] == 4, 'stride x = 4'); + assert(*result[1] == 2, 'stride y = 2'); + assert(*result[2] == 1, 'stride z = 1'); assert(result.len() == 3, 'len = 3'); } } diff --git a/src/tests/operators/tensor/core/stride/stride_i32_test.cairo b/src/tests/operators/tensor/core/stride/stride_i32_test.cairo index b9d7b4b6e..62c923ebd 100644 --- a/src/tests/operators/tensor/core/stride/stride_i32_test.cairo +++ b/src/tests/operators/tensor/core/stride/stride_i32_test.cairo @@ -15,7 +15,7 @@ mod tensor_1D { fn tensor_stride() { let tensor = i32_tensor_1x3_helper(); let result = tensor.stride(); - assert(*result.at(0) == 1, 'stride x = 1'); + assert(*result[0] == 1, 'stride x = 1'); assert(result.len() == 1, 'len = 1'); } } @@ -37,8 +37,8 @@ mod tensor_2D { fn tensor_at() { let tensor = i32_tensor_2x2_helper(); let result = tensor.stride(); - assert(*result.at(0) == 2, 'stride x = 2'); - assert(*result.at(1) == 1, 'stride y = 1'); + assert(*result[0] == 2, 'stride x = 2'); + assert(*result[1] == 1, 'stride y = 1'); assert(result.len() == 2, 'len = 2'); } } @@ -60,9 +60,9 @@ mod tensor_3D { fn tensor_at() { let tensor = i32_tensor_2x2x2_helper(); let result = tensor.stride(); - assert(*result.at(0) == 4, 'stride x = 4'); - assert(*result.at(1) == 2, 'stride y = 2'); - assert(*result.at(2) == 1, 'stride z = 1'); + assert(*result[0] == 4, 'stride x = 4'); + assert(*result[1] == 2, 'stride y = 2'); + assert(*result[2] == 1, 'stride z = 1'); assert(result.len() == 3, 'len = 3'); } } diff --git a/src/tests/operators/tensor/core/stride/stride_u32_test.cairo b/src/tests/operators/tensor/core/stride/stride_u32_test.cairo index 5fb0607ba..7dffbc763 100644 --- a/src/tests/operators/tensor/core/stride/stride_u32_test.cairo +++ b/src/tests/operators/tensor/core/stride/stride_u32_test.cairo @@ -15,7 +15,7 @@ mod tensor_1D { fn tensor_stride() { let tensor = u32_tensor_1x3_helper(); let result = tensor.stride(); - assert(*result.at(0) == 1, 'stride x = 1'); + assert(*result[0] == 1, 'stride x = 1'); assert(result.len() == 1, 'len = 1'); } } @@ -37,8 +37,8 @@ mod tensor_2D { fn tensor_at() { let tensor = u32_tensor_2x2_helper(); let result = tensor.stride(); - assert(*result.at(0) == 2, 'stride x = 2'); - assert(*result.at(1) == 1, 'stride y = 1'); + assert(*result[0] == 2, 'stride x = 2'); + assert(*result[1] == 1, 'stride y = 1'); assert(result.len() == 2, 'len = 2'); } } @@ -60,9 +60,9 @@ mod tensor_3D { fn tensor_at() { let tensor = u32_tensor_2x2x2_helper(); let result = tensor.stride(); - assert(*result.at(0) == 4, 'stride x = 4'); - assert(*result.at(1) == 2, 'stride y = 2'); - assert(*result.at(2) == 1, 'stride z = 1'); + assert(*result[0] == 4, 'stride x = 4'); + assert(*result[1] == 2, 'stride y = 2'); + assert(*result[2] == 1, 'stride z = 1'); assert(result.len() == 3, 'len = 3'); } } diff --git a/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp16x16_test.cairo b/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp16x16_test.cairo index 8b5dd219d..efc34e156 100644 --- a/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp16x16_test.cairo +++ b/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp16x16_test.cairo @@ -49,38 +49,38 @@ mod tensor_2D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); let tensor = fp_tensor_3x2_helper(); let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(3, false), 'result[4] = 3'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 3, 'shape[1] = 3'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.data[3] == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.data[4] == FixedTrait::new_unscaled(3, false), 'result[4] = 3'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 3, 'shape[1] = 3'); let tensor = fp_tensor_2x3_helper(); let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(3, false), 'result[1] = 3'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.shape.at(0) == 3, 'shape[0] = 3'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(3, false), 'result[1] = 3'); + assert(*result.data[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data[3] == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result.data[4] == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.shape[0] == 3, 'shape[0] = 3'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); } } @@ -112,14 +112,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(5, false), 'result[3] = 5'); - assert(*result.at(4) == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); - assert(*result.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); - assert(*result.at(6) == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); - assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(5, false), 'result[3] = 5'); + assert(*result[4] == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); + assert(*result[5] == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result[6] == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); + assert(*result[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); let mut axes: Array = ArrayTrait::new(); axes.append(2); @@ -128,14 +128,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); - assert(*result.at(2) == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); - assert(*result.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.at(6) == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); - assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result[3] == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result[4] == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result[6] == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); + assert(*result[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); let mut axes: Array = ArrayTrait::new(); axes.append(0); @@ -144,14 +144,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); - assert(*result.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); - assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result[5] == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result[6] == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); let tensor = fp_tensor_3x2x2_helper(); @@ -162,21 +162,21 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(5, false), 'result[4] = 5'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(9, false), 'result[5] = 9'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); - assert(*result.data.at(8) == FixedTrait::new_unscaled(10, false), 'result[8] = 10'); - assert(*result.data.at(9) == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); - assert(*result.data.at(10) == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); - assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.data[2] == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert(*result.data[3] == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.data[4] == FixedTrait::new_unscaled(5, false), 'result[4] = 5'); + assert(*result.data[5] == FixedTrait::new_unscaled(9, false), 'result[5] = 9'); + assert(*result.data[6] == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data[7] == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); + assert(*result.data[8] == FixedTrait::new_unscaled(10, false), 'result[8] = 10'); + assert(*result.data[9] == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); + assert(*result.data[10] == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); + assert(*result.data[11] == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 3, 'shape[2] = 3'); let mut axes: Array = ArrayTrait::new(); axes.append(2); @@ -185,21 +185,21 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(6, false), 'result[4] = 6'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(5, false), 'result[7] = 5'); - assert(*result.data.at(8) == FixedTrait::new_unscaled(9, false), 'result[8] = 9'); - assert(*result.data.at(9) == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); - assert(*result.data.at(10) == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); - assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.data[2] == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert(*result.data[3] == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result.data[4] == FixedTrait::new_unscaled(6, false), 'result[4] = 6'); + assert(*result.data[5] == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); + assert(*result.data[6] == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); + assert(*result.data[7] == FixedTrait::new_unscaled(5, false), 'result[7] = 5'); + assert(*result.data[8] == FixedTrait::new_unscaled(9, false), 'result[8] = 9'); + assert(*result.data[9] == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); + assert(*result.data[10] == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); + assert(*result.data[11] == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 3, 'shape[2] = 3'); let mut axes: Array = ArrayTrait::new(); axes.append(0); @@ -208,20 +208,20 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); - assert(*result.data.at(8) == FixedTrait::new_unscaled(8, false), 'result[8] = 8'); - assert(*result.data.at(9) == FixedTrait::new_unscaled(10, false), 'result[9] = 10'); - assert(*result.data.at(10) == FixedTrait::new_unscaled(9, false), 'result[10] = 9'); - assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); - assert(*result.shape.at(0) == 3, 'shape[0] = 3'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 2, 'shape[2] = 2'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data[5] == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result.data[6] == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result.data[8] == FixedTrait::new_unscaled(8, false), 'result[8] = 8'); + assert(*result.data[9] == FixedTrait::new_unscaled(10, false), 'result[9] = 10'); + assert(*result.data[10] == FixedTrait::new_unscaled(9, false), 'result[10] = 9'); + assert(*result.data[11] == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape[0] == 3, 'shape[0] = 3'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 2, 'shape[2] = 2'); } } diff --git a/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp8x23_test.cairo b/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp8x23_test.cairo index a160f7020..118dae6f0 100644 --- a/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp8x23_test.cairo +++ b/src/tests/operators/tensor/core/transpose/transpose_fp_test/transpose_fp8x23_test.cairo @@ -49,38 +49,38 @@ mod tensor_2D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); let tensor = fp_tensor_3x2_helper(); let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(3, false), 'result[4] = 3'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 3, 'shape[1] = 3'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result.data[3] == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.data[4] == FixedTrait::new_unscaled(3, false), 'result[4] = 3'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 3, 'shape[1] = 3'); let tensor = fp_tensor_2x3_helper(); let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(3, false), 'result[1] = 3'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.shape.at(0) == 3, 'shape[0] = 3'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(3, false), 'result[1] = 3'); + assert(*result.data[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data[3] == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result.data[4] == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); + assert(*result.data[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result.shape[0] == 3, 'shape[0] = 3'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); } } @@ -112,14 +112,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(5, false), 'result[3] = 5'); - assert(*result.at(4) == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); - assert(*result.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); - assert(*result.at(6) == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); - assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(5, false), 'result[3] = 5'); + assert(*result[4] == FixedTrait::new_unscaled(2, false), 'result[4] = 2'); + assert(*result[5] == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result[6] == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); + assert(*result[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); let mut axes: Array = ArrayTrait::new(); axes.append(2); @@ -128,14 +128,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); - assert(*result.at(2) == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); - assert(*result.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.at(6) == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); - assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result[3] == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result[4] == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result[6] == FixedTrait::new_unscaled(3, false), 'result[6] = 3'); + assert(*result[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); let mut axes: Array = ArrayTrait::new(); axes.append(0); @@ -144,14 +144,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); - assert(*result.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); - assert(*result.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result[5] == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result[6] == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); let tensor = fp_tensor_3x2x2_helper(); @@ -162,21 +162,21 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(5, false), 'result[4] = 5'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(9, false), 'result[5] = 9'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); - assert(*result.data.at(8) == FixedTrait::new_unscaled(10, false), 'result[8] = 10'); - assert(*result.data.at(9) == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); - assert(*result.data.at(10) == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); - assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.data[2] == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert(*result.data[3] == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result.data[4] == FixedTrait::new_unscaled(5, false), 'result[4] = 5'); + assert(*result.data[5] == FixedTrait::new_unscaled(9, false), 'result[5] = 9'); + assert(*result.data[6] == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data[7] == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); + assert(*result.data[8] == FixedTrait::new_unscaled(10, false), 'result[8] = 10'); + assert(*result.data[9] == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); + assert(*result.data[10] == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); + assert(*result.data[11] == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 3, 'shape[2] = 3'); let mut axes: Array = ArrayTrait::new(); axes.append(2); @@ -185,21 +185,21 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(6, false), 'result[4] = 6'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(5, false), 'result[7] = 5'); - assert(*result.data.at(8) == FixedTrait::new_unscaled(9, false), 'result[8] = 9'); - assert(*result.data.at(9) == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); - assert(*result.data.at(10) == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); - assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(4, false), 'result[1] = 4'); + assert(*result.data[2] == FixedTrait::new_unscaled(8, false), 'result[2] = 8'); + assert(*result.data[3] == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result.data[4] == FixedTrait::new_unscaled(6, false), 'result[4] = 6'); + assert(*result.data[5] == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); + assert(*result.data[6] == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); + assert(*result.data[7] == FixedTrait::new_unscaled(5, false), 'result[7] = 5'); + assert(*result.data[8] == FixedTrait::new_unscaled(9, false), 'result[8] = 9'); + assert(*result.data[9] == FixedTrait::new_unscaled(3, false), 'result[9] = 3'); + assert(*result.data[10] == FixedTrait::new_unscaled(7, false), 'result[10] = 7'); + assert(*result.data[11] == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 3, 'shape[2] = 3'); let mut axes: Array = ArrayTrait::new(); axes.append(0); @@ -208,20 +208,20 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); - assert(*result.data.at(8) == FixedTrait::new_unscaled(8, false), 'result[8] = 8'); - assert(*result.data.at(9) == FixedTrait::new_unscaled(10, false), 'result[9] = 10'); - assert(*result.data.at(10) == FixedTrait::new_unscaled(9, false), 'result[10] = 9'); - assert(*result.data.at(11) == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); - assert(*result.shape.at(0) == 3, 'shape[0] = 3'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 2, 'shape[2] = 2'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result.data[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result.data[3] == FixedTrait::new_unscaled(3, false), 'result[3] = 3'); + assert(*result.data[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result.data[5] == FixedTrait::new_unscaled(6, false), 'result[5] = 6'); + assert(*result.data[6] == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result.data[7] == FixedTrait::new_unscaled(7, false), 'result[7] = 7'); + assert(*result.data[8] == FixedTrait::new_unscaled(8, false), 'result[8] = 8'); + assert(*result.data[9] == FixedTrait::new_unscaled(10, false), 'result[9] = 10'); + assert(*result.data[10] == FixedTrait::new_unscaled(9, false), 'result[10] = 9'); + assert(*result.data[11] == FixedTrait::new_unscaled(11, false), 'result[11] = 11'); + assert(*result.shape[0] == 3, 'shape[0] = 3'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 2, 'shape[2] = 2'); } } diff --git a/src/tests/operators/tensor/core/transpose/transpose_u32_test.cairo b/src/tests/operators/tensor/core/transpose/transpose_u32_test.cairo index 902c0f5c0..eb2872258 100644 --- a/src/tests/operators/tensor/core/transpose/transpose_u32_test.cairo +++ b/src/tests/operators/tensor/core/transpose/transpose_u32_test.cairo @@ -48,38 +48,38 @@ mod tensor_2D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 2, 'result[1] = 2'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 3, 'result[3] = 3'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 2, 'result[1] = 2'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 3, 'result[3] = 3'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); let tensor = u32_tensor_3x2_helper(); let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 2, 'result[1] = 2'); - assert(*result.data.at(2) == 4, 'result[2] = 4'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); - assert(*result.data.at(4) == 3, 'result[4] = 3'); - assert(*result.data.at(5) == 5, 'result[5] = 5'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 3, 'shape[1] = 3'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 2, 'result[1] = 2'); + assert(*result.data[2] == 4, 'result[2] = 4'); + assert(*result.data[3] == 1, 'result[3] = 1'); + assert(*result.data[4] == 3, 'result[4] = 3'); + assert(*result.data[5] == 5, 'result[5] = 5'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 3, 'shape[1] = 3'); let tensor = u32_tensor_2x3_helper(); let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 3, 'result[1] = 3'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 4, 'result[3] = 4'); - assert(*result.data.at(4) == 2, 'result[4] = 2'); - assert(*result.data.at(5) == 5, 'result[5] = 5'); - assert(*result.shape.at(0) == 3, 'shape[0] = 3'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 3, 'result[1] = 3'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 4, 'result[3] = 4'); + assert(*result.data[4] == 2, 'result[4] = 2'); + assert(*result.data[5] == 5, 'result[5] = 5'); + assert(*result.shape[0] == 3, 'shape[0] = 3'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); } } @@ -108,14 +108,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 4, 'result[1] = 4'); - assert(*result.at(2) == 1, 'result[2] = 1'); - assert(*result.at(3) == 5, 'result[3] = 5'); - assert(*result.at(4) == 2, 'result[4] = 2'); - assert(*result.at(5) == 6, 'result[5] = 6'); - assert(*result.at(6) == 3, 'result[6] = 3'); - assert(*result.at(7) == 7, 'result[7] = 7'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 4, 'result[1] = 4'); + assert(*result[2] == 1, 'result[2] = 1'); + assert(*result[3] == 5, 'result[3] = 5'); + assert(*result[4] == 2, 'result[4] = 2'); + assert(*result[5] == 6, 'result[5] = 6'); + assert(*result[6] == 3, 'result[6] = 3'); + assert(*result[7] == 7, 'result[7] = 7'); let mut axes: Array = ArrayTrait::new(); axes.append(2); @@ -124,14 +124,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 4, 'result[1] = 4'); - assert(*result.at(2) == 2, 'result[2] = 2'); - assert(*result.at(3) == 6, 'result[3] = 6'); - assert(*result.at(4) == 1, 'result[4] = 1'); - assert(*result.at(5) == 5, 'result[5] = 5'); - assert(*result.at(6) == 3, 'result[6] = 3'); - assert(*result.at(7) == 7, 'result[7] = 7'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 4, 'result[1] = 4'); + assert(*result[2] == 2, 'result[2] = 2'); + assert(*result[3] == 6, 'result[3] = 6'); + assert(*result[4] == 1, 'result[4] = 1'); + assert(*result[5] == 5, 'result[5] = 5'); + assert(*result[6] == 3, 'result[6] = 3'); + assert(*result[7] == 7, 'result[7] = 7'); let mut axes: Array = ArrayTrait::new(); axes.append(0); @@ -140,14 +140,14 @@ mod tensor_3D { let result = tensor.transpose(axes.span()).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 2, 'result[1] = 2'); - assert(*result.at(2) == 1, 'result[2] = 1'); - assert(*result.at(3) == 3, 'result[3] = 3'); - assert(*result.at(4) == 4, 'result[4] = 4'); - assert(*result.at(5) == 6, 'result[5] = 6'); - assert(*result.at(6) == 5, 'result[6] = 5'); - assert(*result.at(7) == 7, 'result[7] = 7'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 2, 'result[1] = 2'); + assert(*result[2] == 1, 'result[2] = 1'); + assert(*result[3] == 3, 'result[3] = 3'); + assert(*result[4] == 4, 'result[4] = 4'); + assert(*result[5] == 6, 'result[5] = 6'); + assert(*result[6] == 5, 'result[6] = 5'); + assert(*result[7] == 7, 'result[7] = 7'); let tensor = u32_tensor_3x2x2_helper(); @@ -158,21 +158,21 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 4, 'result[1] = 4'); - assert(*result.data.at(2) == 8, 'result[2] = 8'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); - assert(*result.data.at(4) == 5, 'result[4] = 5'); - assert(*result.data.at(5) == 9, 'result[5] = 9'); - assert(*result.data.at(6) == 2, 'result[6] = 2'); - assert(*result.data.at(7) == 6, 'result[7] = 6'); - assert(*result.data.at(8) == 10, 'result[8] = 10'); - assert(*result.data.at(9) == 3, 'result[9] = 3'); - assert(*result.data.at(10) == 7, 'result[10] = 7'); - assert(*result.data.at(11) == 11, 'result[11] = 11'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 4, 'result[1] = 4'); + assert(*result.data[2] == 8, 'result[2] = 8'); + assert(*result.data[3] == 1, 'result[3] = 1'); + assert(*result.data[4] == 5, 'result[4] = 5'); + assert(*result.data[5] == 9, 'result[5] = 9'); + assert(*result.data[6] == 2, 'result[6] = 2'); + assert(*result.data[7] == 6, 'result[7] = 6'); + assert(*result.data[8] == 10, 'result[8] = 10'); + assert(*result.data[9] == 3, 'result[9] = 3'); + assert(*result.data[10] == 7, 'result[10] = 7'); + assert(*result.data[11] == 11, 'result[11] = 11'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 3, 'shape[2] = 3'); let mut axes: Array = ArrayTrait::new(); axes.append(2); @@ -181,21 +181,21 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 4, 'result[1] = 4'); - assert(*result.data.at(2) == 8, 'result[2] = 8'); - assert(*result.data.at(3) == 2, 'result[3] = 2'); - assert(*result.data.at(4) == 6, 'result[4] = 6'); - assert(*result.data.at(5) == 10, 'result[5] = 10'); - assert(*result.data.at(6) == 1, 'result[6] = 1'); - assert(*result.data.at(7) == 5, 'result[7] = 5'); - assert(*result.data.at(8) == 9, 'result[8] = 9'); - assert(*result.data.at(9) == 3, 'result[9] = 3'); - assert(*result.data.at(10) == 7, 'result[10] = 7'); - assert(*result.data.at(11) == 11, 'result[11] = 11'); - assert(*result.shape.at(0) == 2, 'shape[0] = 2'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 3, 'shape[2] = 3'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 4, 'result[1] = 4'); + assert(*result.data[2] == 8, 'result[2] = 8'); + assert(*result.data[3] == 2, 'result[3] = 2'); + assert(*result.data[4] == 6, 'result[4] = 6'); + assert(*result.data[5] == 10, 'result[5] = 10'); + assert(*result.data[6] == 1, 'result[6] = 1'); + assert(*result.data[7] == 5, 'result[7] = 5'); + assert(*result.data[8] == 9, 'result[8] = 9'); + assert(*result.data[9] == 3, 'result[9] = 3'); + assert(*result.data[10] == 7, 'result[10] = 7'); + assert(*result.data[11] == 11, 'result[11] = 11'); + assert(*result.shape[0] == 2, 'shape[0] = 2'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 3, 'shape[2] = 3'); let mut axes: Array = ArrayTrait::new(); axes.append(0); @@ -204,20 +204,20 @@ mod tensor_3D { let result = tensor.transpose(axes.span()); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 2, 'result[1] = 2'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 3, 'result[3] = 3'); - assert(*result.data.at(4) == 4, 'result[4] = 4'); - assert(*result.data.at(5) == 6, 'result[5] = 6'); - assert(*result.data.at(6) == 5, 'result[6] = 5'); - assert(*result.data.at(7) == 7, 'result[7] = 7'); - assert(*result.data.at(8) == 8, 'result[8] = 8'); - assert(*result.data.at(9) == 10, 'result[9] = 10'); - assert(*result.data.at(10) == 9, 'result[10] = 9'); - assert(*result.data.at(11) == 11, 'result[11] = 11'); - assert(*result.shape.at(0) == 3, 'shape[0] = 3'); - assert(*result.shape.at(1) == 2, 'shape[1] = 2'); - assert(*result.shape.at(2) == 2, 'shape[2] = 2'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 2, 'result[1] = 2'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 3, 'result[3] = 3'); + assert(*result.data[4] == 4, 'result[4] = 4'); + assert(*result.data[5] == 6, 'result[5] = 6'); + assert(*result.data[6] == 5, 'result[6] = 5'); + assert(*result.data[7] == 7, 'result[7] = 7'); + assert(*result.data[8] == 8, 'result[8] = 8'); + assert(*result.data[9] == 10, 'result[9] = 10'); + assert(*result.data[10] == 9, 'result[10] = 9'); + assert(*result.data[11] == 11, 'result[11] = 11'); + assert(*result.shape[0] == 3, 'shape[0] = 3'); + assert(*result.shape[1] == 2, 'shape[1] = 2'); + assert(*result.shape[2] == 2, 'shape[2] = 2'); } } diff --git a/src/tests/operators/tensor/core/unravel_index.cairo b/src/tests/operators/tensor/core/unravel_index.cairo index 27a8ee9c8..a529d0ba9 100644 --- a/src/tests/operators/tensor/core/unravel_index.cairo +++ b/src/tests/operators/tensor/core/unravel_index.cairo @@ -13,7 +13,7 @@ mod tensor_1D { let mut shape = ArrayTrait::new(); shape.append(5); let result = unravel_index(2, shape.span()); - assert(*result.at(0) == 2, 'result[0] = 2'); + assert(*result[0] == 2, 'result[0] = 2'); } } @@ -33,8 +33,8 @@ mod tensor_2D { shape.append(2); shape.append(4); let result = unravel_index(6, shape.span()); - assert(*result.at(0) == 1, 'result[0] = 1'); - assert(*result.at(1) == 2, 'result[1] = 2'); + assert(*result[0] == 1, 'result[0] = 1'); + assert(*result[1] == 2, 'result[1] = 2'); } } @@ -56,8 +56,8 @@ mod tensor_3D { shape.append(4); shape.append(6); let result = unravel_index(42, shape.span()); - assert(*result.at(0) == 1, 'result[0] = 1'); - assert(*result.at(1) == 3, 'result[1] = 3'); - assert(*result.at(2) == 0, 'result[2] = 0'); + assert(*result[0] == 1, 'result[0] = 1'); + assert(*result[1] == 3, 'result[1] = 3'); + assert(*result[2] == 0, 'result[2] = 0'); } } diff --git a/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo index ad57ef789..aa98ef1c6 100644 --- a/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp16x16_test.cairo @@ -28,7 +28,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -42,7 +42,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -70,7 +70,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -95,7 +95,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -104,7 +104,7 @@ mod tensor_1D { //////////////////////////////////////////// let result = tensor.argmax(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -131,15 +131,15 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); let result = tensor.argmax(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -156,8 +156,8 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); let result = tensor.argmax(1,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -183,8 +183,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(1,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -193,8 +193,8 @@ mod tensor_2D { //////////////////////////////////////////// let result = tensor.argmax(1,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -221,30 +221,30 @@ mod tensor_3D { let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmax(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmax(2,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } @@ -260,10 +260,10 @@ mod tensor_3D { let tensor = fp_tensor_2x2x2_helper(); let result = tensor.argmax(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -294,10 +294,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); @@ -306,10 +306,10 @@ mod tensor_3D { // case: select_last_index == true //////////////////////////////////////////// let result = tensor.argmax(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } diff --git a/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo index 020727d37..7f73dd9c1 100644 --- a/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/argmax/argmax_fp_test/argmax_fp8x23_test.cairo @@ -28,7 +28,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -42,7 +42,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -70,7 +70,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -95,7 +95,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -104,7 +104,7 @@ mod tensor_1D { //////////////////////////////////////////// let result = tensor.argmax(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -131,15 +131,15 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); let result = tensor.argmax(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -156,8 +156,8 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); let result = tensor.argmax(1,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -183,8 +183,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(1,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -193,8 +193,8 @@ mod tensor_2D { //////////////////////////////////////////// let result = tensor.argmax(1,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -221,30 +221,30 @@ mod tensor_3D { let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmax(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmax(2,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } @@ -260,10 +260,10 @@ mod tensor_3D { let tensor = fp_tensor_2x2x2_helper(); let result = tensor.argmax(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -294,10 +294,10 @@ mod tensor_3D { let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); @@ -307,10 +307,10 @@ mod tensor_3D { //////////////////////////////////////////// let result = tensor.argmax(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } diff --git a/src/tests/operators/tensor/math/argmax/argmax_i32_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_i32_test.cairo index 19c8744fb..2d53b7cc9 100644 --- a/src/tests/operators/tensor/math/argmax/argmax_i32_test.cairo +++ b/src/tests/operators/tensor/math/argmax/argmax_i32_test.cairo @@ -26,7 +26,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -40,7 +40,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -68,7 +68,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -93,7 +93,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -102,7 +102,7 @@ mod tensor_1D { //////////////////////////////////////////// let result = tensor.argmax(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -126,15 +126,15 @@ mod tensor_2D { let tensor = i32_tensor_2x2_helper(); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); let result = tensor.argmax(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -151,8 +151,8 @@ mod tensor_2D { let tensor = i32_tensor_2x2_helper(); let result = tensor.argmax(1,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -178,8 +178,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(1,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -187,8 +187,8 @@ mod tensor_2D { // case: select_last_index == true //////////////////////////////////////////// let result = tensor.argmax(1,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -212,30 +212,30 @@ mod tensor_3D { let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmax(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmax(2,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } @@ -251,10 +251,10 @@ mod tensor_3D { let tensor = i32_tensor_2x2x2_helper(); let result = tensor.argmax(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -287,10 +287,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); @@ -299,10 +299,10 @@ mod tensor_3D { // case: select_last_index == true //////////////////////////////////////////// let result = tensor.argmax(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } diff --git a/src/tests/operators/tensor/math/argmax/argmax_u32_test.cairo b/src/tests/operators/tensor/math/argmax/argmax_u32_test.cairo index 25496bc6c..b06790c03 100644 --- a/src/tests/operators/tensor/math/argmax/argmax_u32_test.cairo +++ b/src/tests/operators/tensor/math/argmax/argmax_u32_test.cairo @@ -25,7 +25,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -54,7 +54,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -79,7 +79,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -88,7 +88,7 @@ mod tensor_1D { //////////////////////////////////////////// let result = tensor.argmax(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -111,15 +111,15 @@ mod tensor_2D { let tensor = u32_tensor_2x2_helper(); let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); let result = tensor.argmax(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -135,8 +135,8 @@ mod tensor_2D { let tensor = u32_tensor_2x2_helper(); let result = tensor.argmax(1,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -162,8 +162,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(1,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -172,8 +172,8 @@ mod tensor_2D { //////////////////////////////////////////// let result = tensor.argmax(1,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -196,30 +196,30 @@ mod tensor_3D { let result = tensor.argmax(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmax(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmax(2,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } @@ -235,10 +235,10 @@ mod tensor_3D { let tensor = u32_tensor_2x2x2_helper(); let result = tensor.argmax(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -270,10 +270,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmax(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); @@ -282,10 +282,10 @@ mod tensor_3D { // case: select_last_index == true //////////////////////////////////////////// let result = tensor.argmax(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } diff --git a/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo index 1d5c29262..e9c69dbd6 100644 --- a/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp16x16_test.cairo @@ -27,7 +27,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -41,7 +41,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -69,7 +69,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -94,7 +94,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -112,7 +112,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -139,15 +139,15 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); let result = tensor.argmin(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -164,8 +164,8 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); let result = tensor.argmin(1,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -191,8 +191,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(1,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -212,8 +212,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(1,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -240,30 +240,30 @@ mod tensor_3D { let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmin(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmin(2,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } @@ -279,10 +279,10 @@ mod tensor_3D { let tensor = fp_tensor_2x2x2_helper(); let result = tensor.argmin(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -312,10 +312,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); @@ -328,10 +328,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } diff --git a/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo index 8f8e7c4bf..e7652cf96 100644 --- a/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/argmin/argmin_fp_test/argmin_fp8x23_test.cairo @@ -25,7 +25,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(0, Option::None(()), Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -38,7 +38,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(0, Option::None(()), Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -65,7 +65,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(0, Option::Some(false), Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -89,7 +89,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(0, Option::None(()), Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -106,7 +106,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(0, Option::None(()), Option::Some(true)); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -133,14 +133,14 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); let result = tensor.argmin(0, Option::None(()), Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); let result = tensor.argmin(1, Option::None(()), Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -154,8 +154,8 @@ mod tensor_2D { let tensor = fp_tensor_2x2_helper(); let result = tensor.argmin(1, Option::Some(false), Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -179,8 +179,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(1, Option::None(()), Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -200,8 +200,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(1, Option::None(()), Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -228,28 +228,28 @@ mod tensor_3D { let result = tensor.argmin(0, Option::None(()), Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmin(1, Option::None(()), Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmin(2, Option::None(()), Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } @@ -264,10 +264,10 @@ mod tensor_3D { let tensor = fp_tensor_2x2x2_helper(); let result = tensor.argmin(0, Option::Some(false), Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -296,10 +296,10 @@ mod tensor_3D { let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(0, Option::None(()), Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); @@ -310,10 +310,10 @@ mod tensor_3D { let extra = ExtraParams { fixed_point: Option::Some(FixedImpl::FP8x23(())) }; let tensor = TensorTrait::::new(sizes.span(), data.span(), Option::Some(extra)); let result = tensor.argmin(0, Option::None(()), Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } diff --git a/src/tests/operators/tensor/math/argmin/argmin_i32_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_i32_test.cairo index 5c36e4f3d..86942f9a5 100644 --- a/src/tests/operators/tensor/math/argmin/argmin_i32_test.cairo +++ b/src/tests/operators/tensor/math/argmin/argmin_i32_test.cairo @@ -26,7 +26,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -40,7 +40,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -68,7 +68,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -93,7 +93,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -111,7 +111,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -135,15 +135,15 @@ mod tensor_2D { let tensor = i32_tensor_2x2_helper(); let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); let result = tensor.argmin(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -160,8 +160,8 @@ mod tensor_2D { let tensor = i32_tensor_2x2_helper(); let result = tensor.argmin(1,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -187,8 +187,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(1,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -208,8 +208,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(1,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -233,30 +233,30 @@ mod tensor_3D { let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmin(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmin(2,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } @@ -272,10 +272,10 @@ mod tensor_3D { let tensor = i32_tensor_2x2x2_helper(); let result = tensor.argmin(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -308,10 +308,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); @@ -324,10 +324,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } diff --git a/src/tests/operators/tensor/math/argmin/argmin_u32_test.cairo b/src/tests/operators/tensor/math/argmin/argmin_u32_test.cairo index 45e4a7a7c..fb8438231 100644 --- a/src/tests/operators/tensor/math/argmin/argmin_u32_test.cairo +++ b/src/tests/operators/tensor/math/argmin/argmin_u32_test.cairo @@ -25,7 +25,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -54,7 +54,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -79,7 +79,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -97,7 +97,7 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 2, 'result[0] = 2'); + assert(*result.data[0] == 2, 'result[0] = 2'); assert(result.data.len() == 1, 'length == 1'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); } @@ -120,15 +120,15 @@ mod tensor_2D { let tensor = u32_tensor_2x2_helper(); let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); let result = tensor.argmin(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -145,8 +145,8 @@ mod tensor_2D { let tensor = u32_tensor_2x2_helper(); let result = tensor.argmin(1,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 1, 'result.shape.len() == 1'); @@ -172,8 +172,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(1,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -193,8 +193,8 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(1,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); assert(result.data.len() == 2, 'length == 2'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); } @@ -217,30 +217,30 @@ mod tensor_3D { let result = tensor.argmin(0,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmin(1,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); let result = tensor.argmin(2,Option::None(()),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } @@ -256,10 +256,10 @@ mod tensor_3D { let tensor = u32_tensor_2x2x2_helper(); let result = tensor.argmin(0,Option::Some(false),Option::None(())); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 2, 'result.shape.len() == 2'); @@ -292,10 +292,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(false)); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); @@ -308,10 +308,10 @@ mod tensor_3D { let extra = Option::::None(()); let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); let result = tensor.argmin(0,Option::None(()),Option::Some(true)); - assert(*result.data.at(0) == 1, 'result[0] = 1'); - assert(*result.data.at(1) == 1, 'result[1] = 1'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); - assert(*result.data.at(3) == 1, 'result[3] = 1'); + assert(*result.data[0] == 1, 'result[0] = 1'); + assert(*result.data[1] == 1, 'result[1] = 1'); + assert(*result.data[2] == 1, 'result[2] = 1'); + assert(*result.data[3] == 1, 'result[3] = 1'); assert(result.data.len() == 4, 'length == 4'); assert(result.shape.len() == 3, 'result.shape.len() == 3'); } diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp16x16_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp16x16_test.cairo index 7d9c61c71..229d3f460 100644 --- a/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp16x16_test.cairo @@ -20,9 +20,9 @@ mod tensor_1D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); } } @@ -44,9 +44,9 @@ mod tensor_1D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); - assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result[2] == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); } } @@ -68,9 +68,9 @@ mod tensor_1D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); } } @@ -101,8 +101,8 @@ mod tensor_1D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[0] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); } } } @@ -132,10 +132,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[3] == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); } #[test] @@ -153,10 +153,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); - assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); + assert(*result[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result[3] == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -169,10 +169,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); - assert(*result.at(2) == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); - assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result[2] == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); + assert(*result[3] == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); } } @@ -197,10 +197,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); - assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); - assert(*result.at(3) == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result[2] == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result[3] == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); } #[test] @@ -218,10 +218,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); - assert(*result.at(2) == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result[3] == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -234,10 +234,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); } } @@ -262,10 +262,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.at(3) == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[3] == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); } #[test] @@ -283,10 +283,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(100, false), 'result[1] = 100'); - assert(*result.at(2) == FixedTrait::new_unscaled(20, false), 'result[2] = 20'); - assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(100, false), 'result[1] = 100'); + assert(*result[2] == FixedTrait::new_unscaled(20, false), 'result[2] = 20'); + assert(*result[3] == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -299,10 +299,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); - assert(*result.at(2) == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); - assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); + assert(*result[2] == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); + assert(*result[3] == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); } } @@ -336,10 +336,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result[0] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); } #[test] @@ -367,10 +367,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(30, false), 'result[2] = 30'); - assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(30, false), 'result[2] = 30'); + assert(*result[3] == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -383,10 +383,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); - assert(*result.at(2) == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); - assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); + assert(*result[2] == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); + assert(*result[3] == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); } } } @@ -416,14 +416,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); - assert(*result.at(4) == FixedTrait::new_unscaled(8, false), 'result[4] = 8'); - assert(*result.at(5) == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); - assert(*result.at(6) == FixedTrait::new_unscaled(12, false), 'result[6] = 12'); - assert(*result.at(7) == FixedTrait::new_unscaled(14, false), 'result[7] = 14'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[3] == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result[4] == FixedTrait::new_unscaled(8, false), 'result[4] = 8'); + assert(*result[5] == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); + assert(*result[6] == FixedTrait::new_unscaled(12, false), 'result[6] = 12'); + assert(*result[7] == FixedTrait::new_unscaled(14, false), 'result[7] = 14'); } #[test] @@ -443,14 +443,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); - assert(*result.at(2) == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); - assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); - assert(*result.at(4) == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); - assert(*result.at(5) == FixedTrait::new_unscaled(15, false), 'result[5] = 15'); - assert(*result.at(6) == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); - assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result[2] == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); + assert(*result[3] == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result[4] == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); + assert(*result[5] == FixedTrait::new_unscaled(15, false), 'result[5] = 15'); + assert(*result[6] == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); + assert(*result[7] == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -464,14 +464,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); - assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.at(3) == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); - assert(*result.at(4) == FixedTrait::new_unscaled(104, false), 'result[4] = 104'); - assert(*result.at(5) == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); - assert(*result.at(6) == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); - assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result[3] == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); + assert(*result[4] == FixedTrait::new_unscaled(104, false), 'result[4] = 104'); + assert(*result[5] == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); + assert(*result[6] == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); + assert(*result[7] == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(1); @@ -485,14 +485,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); - assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); - assert(*result.at(4) == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); - assert(*result.at(5) == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); - assert(*result.at(6) == FixedTrait::new_unscaled(16, false), 'result[6] = 16'); - assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); + assert(*result[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result[3] == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result[4] == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); + assert(*result[5] == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); + assert(*result[6] == FixedTrait::new_unscaled(16, false), 'result[6] = 16'); + assert(*result[7] == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); } } @@ -517,14 +517,14 @@ mod tensor_3D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); - assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); - assert(*result.at(3) == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); - assert(*result.at(4) == FixedTrait::new_unscaled(0, false), 'result[4] = 0'); - assert(*result.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); - assert(*result.at(6) == FixedTrait::new_unscaled(0, false), 'result[6] = 0'); - assert(*result.at(7) == FixedTrait::new_unscaled(0, false), 'result[7] = 0'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result[2] == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result[3] == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); + assert(*result[4] == FixedTrait::new_unscaled(0, false), 'result[4] = 0'); + assert(*result[5] == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result[6] == FixedTrait::new_unscaled(0, false), 'result[6] = 0'); + assert(*result[7] == FixedTrait::new_unscaled(0, false), 'result[7] = 0'); } #[test] @@ -544,14 +544,14 @@ mod tensor_3D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); - assert(*result.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); - assert(*result.at(7) == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result[6] == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result[7] == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); } } @@ -576,14 +576,14 @@ mod tensor_3D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.at(3) == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); - assert(*result.at(4) == FixedTrait::new_unscaled(16, false), 'result[4] = 16'); - assert(*result.at(5) == FixedTrait::new_unscaled(25, false), 'result[5] = 25'); - assert(*result.at(6) == FixedTrait::new_unscaled(36, false), 'result[6] = 36'); - assert(*result.at(7) == FixedTrait::new_unscaled(49, false), 'result[7] = 49'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[3] == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); + assert(*result[4] == FixedTrait::new_unscaled(16, false), 'result[4] = 16'); + assert(*result[5] == FixedTrait::new_unscaled(25, false), 'result[5] = 25'); + assert(*result[6] == FixedTrait::new_unscaled(36, false), 'result[6] = 36'); + assert(*result[7] == FixedTrait::new_unscaled(49, false), 'result[7] = 49'); } #[test] @@ -603,14 +603,14 @@ mod tensor_3D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); - assert(*result.at(2) == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); - assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); - assert(*result.at(4) == FixedTrait::new_unscaled(40, false), 'result[4] = 40'); - assert(*result.at(5) == FixedTrait::new_unscaled(50, false), 'result[5] = 50'); - assert(*result.at(6) == FixedTrait::new_unscaled(600, false), 'result[6] = 600'); - assert(*result.at(7) == FixedTrait::new_unscaled(700, false), 'result[7] = 700'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); + assert(*result[2] == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); + assert(*result[3] == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + assert(*result[4] == FixedTrait::new_unscaled(40, false), 'result[4] = 40'); + assert(*result[5] == FixedTrait::new_unscaled(50, false), 'result[5] = 50'); + assert(*result[6] == FixedTrait::new_unscaled(600, false), 'result[6] = 600'); + assert(*result[7] == FixedTrait::new_unscaled(700, false), 'result[7] = 700'); } } @@ -648,14 +648,14 @@ mod tensor_3D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); - assert(*result.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.at(5) == FixedTrait::new_unscaled(1, false), 'result[5] = 1'); - assert(*result.at(6) == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); - assert(*result.at(7) == FixedTrait::new_unscaled(1, false), 'result[7] = 1'); + assert(*result[0] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result[4] == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result[5] == FixedTrait::new_unscaled(1, false), 'result[5] = 1'); + assert(*result[6] == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); + assert(*result[7] == FixedTrait::new_unscaled(1, false), 'result[7] = 1'); } #[test] @@ -689,14 +689,14 @@ mod tensor_3D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); - assert(*result.at(2) == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); - assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); - assert(*result.at(4) == FixedTrait::new_unscaled(50, false), 'result[4] = 50'); - assert(*result.at(5) == FixedTrait::new_unscaled(60, false), 'result[5] = 60'); - assert(*result.at(6) == FixedTrait::new_unscaled(7, false), 'result[6] = 7'); - assert(*result.at(7) == FixedTrait::new_unscaled(8, false), 'result[7] = 8'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); + assert(*result[2] == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); + assert(*result[3] == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result[4] == FixedTrait::new_unscaled(50, false), 'result[4] = 50'); + assert(*result[5] == FixedTrait::new_unscaled(60, false), 'result[5] = 60'); + assert(*result[6] == FixedTrait::new_unscaled(7, false), 'result[6] = 7'); + assert(*result[7] == FixedTrait::new_unscaled(8, false), 'result[7] = 8'); } } } diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp8x23_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp8x23_test.cairo index 0f779e5b4..976f8c343 100644 --- a/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_fp_test/arithmetic_fp8x23_test.cairo @@ -20,9 +20,9 @@ mod tensor_1D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); } } @@ -44,9 +44,9 @@ mod tensor_1D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); - assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result[2] == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); } } @@ -68,9 +68,9 @@ mod tensor_1D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); } } @@ -102,8 +102,8 @@ mod tensor_1D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[0] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); } } } @@ -133,10 +133,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[3] == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); } #[test] @@ -155,10 +155,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); - assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); + assert(*result[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result[3] == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -172,10 +172,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); - assert(*result.at(2) == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); - assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result[2] == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); + assert(*result[3] == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); } } @@ -200,10 +200,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); - assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); - assert(*result.at(3) == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result[2] == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result[3] == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); } #[test] @@ -222,10 +222,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); - assert(*result.at(2) == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); - assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result[2] == FixedTrait::new_unscaled(2, false), 'result[2] = 2'); + assert(*result[3] == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -239,10 +239,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); } } @@ -267,10 +267,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.at(3) == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[3] == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); } #[test] @@ -289,10 +289,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(100, false), 'result[1] = 100'); - assert(*result.at(2) == FixedTrait::new_unscaled(20, false), 'result[2] = 20'); - assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(100, false), 'result[1] = 100'); + assert(*result[2] == FixedTrait::new_unscaled(20, false), 'result[2] = 20'); + assert(*result[3] == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -306,10 +306,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); - assert(*result.at(2) == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); - assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); + assert(*result[2] == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); + assert(*result[3] == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); } } @@ -344,10 +344,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result[0] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); } #[test] @@ -377,10 +377,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(30, false), 'result[2] = 30'); - assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(30, false), 'result[2] = 30'); + assert(*result[3] == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -394,10 +394,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); - assert(*result.at(2) == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); - assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); + assert(*result[2] == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); + assert(*result[3] == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); } } } @@ -427,14 +427,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.at(3) == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); - assert(*result.at(4) == FixedTrait::new_unscaled(8, false), 'result[4] = 8'); - assert(*result.at(5) == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); - assert(*result.at(6) == FixedTrait::new_unscaled(12, false), 'result[6] = 12'); - assert(*result.at(7) == FixedTrait::new_unscaled(14, false), 'result[7] = 14'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(2, false), 'result[1] = 2'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[3] == FixedTrait::new_unscaled(6, false), 'result[3] = 6'); + assert(*result[4] == FixedTrait::new_unscaled(8, false), 'result[4] = 8'); + assert(*result[5] == FixedTrait::new_unscaled(10, false), 'result[5] = 10'); + assert(*result[6] == FixedTrait::new_unscaled(12, false), 'result[6] = 12'); + assert(*result[7] == FixedTrait::new_unscaled(14, false), 'result[7] = 14'); } #[test] @@ -455,14 +455,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); - assert(*result.at(2) == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); - assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); - assert(*result.at(4) == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); - assert(*result.at(5) == FixedTrait::new_unscaled(15, false), 'result[5] = 15'); - assert(*result.at(6) == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); - assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result[2] == FixedTrait::new_unscaled(102, false), 'result[2] = 102'); + assert(*result[3] == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result[4] == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); + assert(*result[5] == FixedTrait::new_unscaled(15, false), 'result[5] = 15'); + assert(*result[6] == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); + assert(*result[7] == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -477,14 +477,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); - assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.at(3) == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); - assert(*result.at(4) == FixedTrait::new_unscaled(104, false), 'result[4] = 104'); - assert(*result.at(5) == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); - assert(*result.at(6) == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); - assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(11, false), 'result[1] = 11'); + assert(*result[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result[3] == FixedTrait::new_unscaled(13, false), 'result[3] = 13'); + assert(*result[4] == FixedTrait::new_unscaled(104, false), 'result[4] = 104'); + assert(*result[5] == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); + assert(*result[6] == FixedTrait::new_unscaled(106, false), 'result[6] = 106'); + assert(*result[7] == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(1); @@ -499,14 +499,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); - assert(*result.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.at(3) == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); - assert(*result.at(4) == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); - assert(*result.at(5) == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); - assert(*result.at(6) == FixedTrait::new_unscaled(16, false), 'result[6] = 16'); - assert(*result.at(7) == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(101, false), 'result[1] = 101'); + assert(*result[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result[3] == FixedTrait::new_unscaled(103, false), 'result[3] = 103'); + assert(*result[4] == FixedTrait::new_unscaled(14, false), 'result[4] = 14'); + assert(*result[5] == FixedTrait::new_unscaled(105, false), 'result[5] = 105'); + assert(*result[6] == FixedTrait::new_unscaled(16, false), 'result[6] = 16'); + assert(*result[7] == FixedTrait::new_unscaled(107, false), 'result[7] = 107'); } } @@ -531,14 +531,14 @@ mod tensor_3D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); - assert(*result.at(2) == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); - assert(*result.at(3) == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); - assert(*result.at(4) == FixedTrait::new_unscaled(0, false), 'result[4] = 0'); - assert(*result.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); - assert(*result.at(6) == FixedTrait::new_unscaled(0, false), 'result[6] = 0'); - assert(*result.at(7) == FixedTrait::new_unscaled(0, false), 'result[7] = 0'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(0, false), 'result[1] = 0'); + assert(*result[2] == FixedTrait::new_unscaled(0, false), 'result[2] = 0'); + assert(*result[3] == FixedTrait::new_unscaled(0, false), 'result[3] = 0'); + assert(*result[4] == FixedTrait::new_unscaled(0, false), 'result[4] = 0'); + assert(*result[5] == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result[6] == FixedTrait::new_unscaled(0, false), 'result[6] = 0'); + assert(*result[7] == FixedTrait::new_unscaled(0, false), 'result[7] = 0'); } #[test] @@ -559,14 +559,14 @@ mod tensor_3D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); - assert(*result.at(4) == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); - assert(*result.at(5) == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); - assert(*result.at(6) == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); - assert(*result.at(7) == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(2, false), 'result[3] = 2'); + assert(*result[4] == FixedTrait::new_unscaled(4, false), 'result[4] = 4'); + assert(*result[5] == FixedTrait::new_unscaled(5, false), 'result[5] = 5'); + assert(*result[6] == FixedTrait::new_unscaled(5, false), 'result[6] = 5'); + assert(*result[7] == FixedTrait::new_unscaled(6, false), 'result[7] = 6'); } } @@ -591,14 +591,14 @@ mod tensor_3D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); - assert(*result.at(3) == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); - assert(*result.at(4) == FixedTrait::new_unscaled(16, false), 'result[4] = 16'); - assert(*result.at(5) == FixedTrait::new_unscaled(25, false), 'result[5] = 25'); - assert(*result.at(6) == FixedTrait::new_unscaled(36, false), 'result[6] = 36'); - assert(*result.at(7) == FixedTrait::new_unscaled(49, false), 'result[7] = 49'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(4, false), 'result[2] = 4'); + assert(*result[3] == FixedTrait::new_unscaled(9, false), 'result[3] = 9'); + assert(*result[4] == FixedTrait::new_unscaled(16, false), 'result[4] = 16'); + assert(*result[5] == FixedTrait::new_unscaled(25, false), 'result[5] = 25'); + assert(*result[6] == FixedTrait::new_unscaled(36, false), 'result[6] = 36'); + assert(*result[7] == FixedTrait::new_unscaled(49, false), 'result[7] = 49'); } #[test] @@ -619,14 +619,14 @@ mod tensor_3D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.at(1) == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); - assert(*result.at(2) == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); - assert(*result.at(3) == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); - assert(*result.at(4) == FixedTrait::new_unscaled(40, false), 'result[4] = 40'); - assert(*result.at(5) == FixedTrait::new_unscaled(50, false), 'result[5] = 50'); - assert(*result.at(6) == FixedTrait::new_unscaled(600, false), 'result[6] = 600'); - assert(*result.at(7) == FixedTrait::new_unscaled(700, false), 'result[7] = 700'); + assert(*result[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result[1] == FixedTrait::new_unscaled(10, false), 'result[1] = 10'); + assert(*result[2] == FixedTrait::new_unscaled(200, false), 'result[2] = 200'); + assert(*result[3] == FixedTrait::new_unscaled(300, false), 'result[3] = 300'); + assert(*result[4] == FixedTrait::new_unscaled(40, false), 'result[4] = 40'); + assert(*result[5] == FixedTrait::new_unscaled(50, false), 'result[5] = 50'); + assert(*result[6] == FixedTrait::new_unscaled(600, false), 'result[6] = 600'); + assert(*result[7] == FixedTrait::new_unscaled(700, false), 'result[7] = 700'); } } @@ -665,14 +665,14 @@ mod tensor_3D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); - assert(*result.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.at(2) == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); - assert(*result.at(3) == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); - assert(*result.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.at(5) == FixedTrait::new_unscaled(1, false), 'result[5] = 1'); - assert(*result.at(6) == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); - assert(*result.at(7) == FixedTrait::new_unscaled(1, false), 'result[7] = 1'); + assert(*result[0] == FixedTrait::new_unscaled(1, false), 'result[0] = 1'); + assert(*result[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result[2] == FixedTrait::new_unscaled(1, false), 'result[2] = 1'); + assert(*result[3] == FixedTrait::new_unscaled(1, false), 'result[3] = 1'); + assert(*result[4] == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result[5] == FixedTrait::new_unscaled(1, false), 'result[5] = 1'); + assert(*result[6] == FixedTrait::new_unscaled(1, false), 'result[6] = 1'); + assert(*result[7] == FixedTrait::new_unscaled(1, false), 'result[7] = 1'); } #[test] @@ -708,14 +708,14 @@ mod tensor_3D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); - assert(*result.at(1) == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); - assert(*result.at(2) == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); - assert(*result.at(3) == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); - assert(*result.at(4) == FixedTrait::new_unscaled(50, false), 'result[4] = 50'); - assert(*result.at(5) == FixedTrait::new_unscaled(60, false), 'result[5] = 60'); - assert(*result.at(6) == FixedTrait::new_unscaled(7, false), 'result[6] = 7'); - assert(*result.at(7) == FixedTrait::new_unscaled(8, false), 'result[7] = 8'); + assert(*result[0] == FixedTrait::new_unscaled(10, false), 'result[0] = 10'); + assert(*result[1] == FixedTrait::new_unscaled(20, false), 'result[1] = 20'); + assert(*result[2] == FixedTrait::new_unscaled(3, false), 'result[2] = 3'); + assert(*result[3] == FixedTrait::new_unscaled(4, false), 'result[3] = 4'); + assert(*result[4] == FixedTrait::new_unscaled(50, false), 'result[4] = 50'); + assert(*result[5] == FixedTrait::new_unscaled(60, false), 'result[5] = 60'); + assert(*result[6] == FixedTrait::new_unscaled(7, false), 'result[6] = 7'); + assert(*result[7] == FixedTrait::new_unscaled(8, false), 'result[7] = 8'); } } } diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_i32_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_i32_test.cairo index 74a110e6d..7430a8bc2 100644 --- a/src/tests/operators/tensor/math/arithmetic/arithmetic_i32_test.cairo +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_i32_test.cairo @@ -19,9 +19,9 @@ mod tensor_1D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(2, false), 'result[1] = 2'); - assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(2, false), 'result[1] = 2'); + assert(*result[2] == IntegerTrait::new(4, false), 'result[2] = 4'); } } @@ -42,9 +42,9 @@ mod tensor_1D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(0, false), 'result[1] = 0'); - assert(*result.at(2) == IntegerTrait::new(0, false), 'result[2] = 0'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(0, false), 'result[1] = 0'); + assert(*result[2] == IntegerTrait::new(0, false), 'result[2] = 0'); } } @@ -65,9 +65,9 @@ mod tensor_1D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); - assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result[2] == IntegerTrait::new(4, false), 'result[2] = 4'); } } @@ -95,8 +95,8 @@ mod tensor_1D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(1, false), 'result[0] = 1'); - assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result[0] == IntegerTrait::new(1, false), 'result[0] = 1'); + assert(*result[1] == IntegerTrait::new(1, false), 'result[1] = 1'); } } } @@ -123,10 +123,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(2, false), 'result[1] = 2'); - assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); - assert(*result.at(3) == IntegerTrait::new(6, false), 'result[3] = 6'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(2, false), 'result[1] = 2'); + assert(*result[2] == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result[3] == IntegerTrait::new(6, false), 'result[3] = 6'); } #[test] @@ -144,10 +144,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); - assert(*result.at(1) == IntegerTrait::new(101, false), 'result[1] = 101'); - assert(*result.at(2) == IntegerTrait::new(12, false), 'result[2] = 12'); - assert(*result.at(3) == IntegerTrait::new(103, false), 'result[3] = 103'); + assert(*result[0] == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result[1] == IntegerTrait::new(101, false), 'result[1] = 101'); + assert(*result[2] == IntegerTrait::new(12, false), 'result[2] = 12'); + assert(*result[3] == IntegerTrait::new(103, false), 'result[3] = 103'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -160,10 +160,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); - assert(*result.at(1) == IntegerTrait::new(11, false), 'result[1] = 11'); - assert(*result.at(2) == IntegerTrait::new(102, false), 'result[2] = 102'); - assert(*result.at(3) == IntegerTrait::new(103, false), 'result[3] = 103'); + assert(*result[0] == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result[1] == IntegerTrait::new(11, false), 'result[1] = 11'); + assert(*result[2] == IntegerTrait::new(102, false), 'result[2] = 102'); + assert(*result[3] == IntegerTrait::new(103, false), 'result[3] = 103'); } } @@ -185,10 +185,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(0, false), 'result[1] = 0'); - assert(*result.at(2) == IntegerTrait::new(0, false), 'result[2] = 0'); - assert(*result.at(3) == IntegerTrait::new(0, false), 'result[3] = 0'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(0, false), 'result[1] = 0'); + assert(*result[2] == IntegerTrait::new(0, false), 'result[2] = 0'); + assert(*result[3] == IntegerTrait::new(0, false), 'result[3] = 0'); } #[test] @@ -206,10 +206,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(0, false), 'result[1] = 0'); - assert(*result.at(2) == IntegerTrait::new(2, false), 'result[2] = 2'); - assert(*result.at(3) == IntegerTrait::new(2, false), 'result[3] = 2'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(0, false), 'result[1] = 0'); + assert(*result[2] == IntegerTrait::new(2, false), 'result[2] = 2'); + assert(*result[3] == IntegerTrait::new(2, false), 'result[3] = 2'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -222,10 +222,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); - assert(*result.at(2) == IntegerTrait::new(1, false), 'result[2] = 1'); - assert(*result.at(3) == IntegerTrait::new(2, false), 'result[3] = 2'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result[2] == IntegerTrait::new(1, false), 'result[2] = 1'); + assert(*result[3] == IntegerTrait::new(2, false), 'result[3] = 2'); } } @@ -247,10 +247,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); - assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); - assert(*result.at(3) == IntegerTrait::new(9, false), 'result[3] = 9'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result[2] == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result[3] == IntegerTrait::new(9, false), 'result[3] = 9'); } #[test] @@ -268,10 +268,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(100, false), 'result[1] = 100'); - assert(*result.at(2) == IntegerTrait::new(20, false), 'result[2] = 20'); - assert(*result.at(3) == IntegerTrait::new(300, false), 'result[3] = 300'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(100, false), 'result[1] = 100'); + assert(*result[2] == IntegerTrait::new(20, false), 'result[2] = 20'); + assert(*result[3] == IntegerTrait::new(300, false), 'result[3] = 300'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -284,10 +284,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(10, false), 'result[1] = 10'); - assert(*result.at(2) == IntegerTrait::new(200, false), 'result[2] = 200'); - assert(*result.at(3) == IntegerTrait::new(300, false), 'result[3] = 300'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(10, false), 'result[1] = 10'); + assert(*result[2] == IntegerTrait::new(200, false), 'result[2] = 200'); + assert(*result[3] == IntegerTrait::new(300, false), 'result[3] = 300'); } } @@ -318,10 +318,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(1, false), 'result[0] = 1'); - assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); - assert(*result.at(2) == IntegerTrait::new(1, false), 'result[2] = 1'); - assert(*result.at(3) == IntegerTrait::new(1, false), 'result[3] = 1'); + assert(*result[0] == IntegerTrait::new(1, false), 'result[0] = 1'); + assert(*result[1] == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result[2] == IntegerTrait::new(1, false), 'result[2] = 1'); + assert(*result[3] == IntegerTrait::new(1, false), 'result[3] = 1'); } #[test] @@ -349,10 +349,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); - assert(*result.at(1) == IntegerTrait::new(2, false), 'result[1] = 2'); - assert(*result.at(2) == IntegerTrait::new(30, false), 'result[2] = 30'); - assert(*result.at(3) == IntegerTrait::new(4, false), 'result[3] = 4'); + assert(*result[0] == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result[1] == IntegerTrait::new(2, false), 'result[1] = 2'); + assert(*result[2] == IntegerTrait::new(30, false), 'result[2] = 30'); + assert(*result[3] == IntegerTrait::new(4, false), 'result[3] = 4'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -365,10 +365,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); - assert(*result.at(1) == IntegerTrait::new(20, false), 'result[1] = 20'); - assert(*result.at(2) == IntegerTrait::new(3, false), 'result[2] = 3'); - assert(*result.at(3) == IntegerTrait::new(4, false), 'result[3] = 4'); + assert(*result[0] == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result[1] == IntegerTrait::new(20, false), 'result[1] = 20'); + assert(*result[2] == IntegerTrait::new(3, false), 'result[2] = 3'); + assert(*result[3] == IntegerTrait::new(4, false), 'result[3] = 4'); } } } @@ -395,14 +395,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(2, false), 'result[1] = 2'); - assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); - assert(*result.at(3) == IntegerTrait::new(6, false), 'result[3] = 6'); - assert(*result.at(4) == IntegerTrait::new(8, false), 'result[4] = 8'); - assert(*result.at(5) == IntegerTrait::new(10, false), 'result[5] = 10'); - assert(*result.at(6) == IntegerTrait::new(12, false), 'result[6] = 12'); - assert(*result.at(7) == IntegerTrait::new(14, false), 'result[7] = 14'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(2, false), 'result[1] = 2'); + assert(*result[2] == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result[3] == IntegerTrait::new(6, false), 'result[3] = 6'); + assert(*result[4] == IntegerTrait::new(8, false), 'result[4] = 8'); + assert(*result[5] == IntegerTrait::new(10, false), 'result[5] = 10'); + assert(*result[6] == IntegerTrait::new(12, false), 'result[6] = 12'); + assert(*result[7] == IntegerTrait::new(14, false), 'result[7] = 14'); } #[test] @@ -422,14 +422,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); - assert(*result.at(1) == IntegerTrait::new(11, false), 'result[1] = 11'); - assert(*result.at(2) == IntegerTrait::new(102, false), 'result[2] = 102'); - assert(*result.at(3) == IntegerTrait::new(103, false), 'result[3] = 103'); - assert(*result.at(4) == IntegerTrait::new(14, false), 'result[4] = 14'); - assert(*result.at(5) == IntegerTrait::new(15, false), 'result[5] = 15'); - assert(*result.at(6) == IntegerTrait::new(106, false), 'result[6] = 106'); - assert(*result.at(7) == IntegerTrait::new(107, false), 'result[7] = 107'); + assert(*result[0] == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result[1] == IntegerTrait::new(11, false), 'result[1] = 11'); + assert(*result[2] == IntegerTrait::new(102, false), 'result[2] = 102'); + assert(*result[3] == IntegerTrait::new(103, false), 'result[3] = 103'); + assert(*result[4] == IntegerTrait::new(14, false), 'result[4] = 14'); + assert(*result[5] == IntegerTrait::new(15, false), 'result[5] = 15'); + assert(*result[6] == IntegerTrait::new(106, false), 'result[6] = 106'); + assert(*result[7] == IntegerTrait::new(107, false), 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -443,14 +443,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); - assert(*result.at(1) == IntegerTrait::new(11, false), 'result[1] = 11'); - assert(*result.at(2) == IntegerTrait::new(12, false), 'result[2] = 12'); - assert(*result.at(3) == IntegerTrait::new(13, false), 'result[3] = 13'); - assert(*result.at(4) == IntegerTrait::new(104, false), 'result[4] = 104'); - assert(*result.at(5) == IntegerTrait::new(105, false), 'result[5] = 105'); - assert(*result.at(6) == IntegerTrait::new(106, false), 'result[6] = 106'); - assert(*result.at(7) == IntegerTrait::new(107, false), 'result[7] = 107'); + assert(*result[0] == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result[1] == IntegerTrait::new(11, false), 'result[1] = 11'); + assert(*result[2] == IntegerTrait::new(12, false), 'result[2] = 12'); + assert(*result[3] == IntegerTrait::new(13, false), 'result[3] = 13'); + assert(*result[4] == IntegerTrait::new(104, false), 'result[4] = 104'); + assert(*result[5] == IntegerTrait::new(105, false), 'result[5] = 105'); + assert(*result[6] == IntegerTrait::new(106, false), 'result[6] = 106'); + assert(*result[7] == IntegerTrait::new(107, false), 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(1); @@ -464,14 +464,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); - assert(*result.at(1) == IntegerTrait::new(101, false), 'result[1] = 101'); - assert(*result.at(2) == IntegerTrait::new(12, false), 'result[2] = 12'); - assert(*result.at(3) == IntegerTrait::new(103, false), 'result[3] = 103'); - assert(*result.at(4) == IntegerTrait::new(14, false), 'result[4] = 14'); - assert(*result.at(5) == IntegerTrait::new(105, false), 'result[5] = 105'); - assert(*result.at(6) == IntegerTrait::new(16, false), 'result[6] = 16'); - assert(*result.at(7) == IntegerTrait::new(107, false), 'result[7] = 107'); + assert(*result[0] == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result[1] == IntegerTrait::new(101, false), 'result[1] = 101'); + assert(*result[2] == IntegerTrait::new(12, false), 'result[2] = 12'); + assert(*result[3] == IntegerTrait::new(103, false), 'result[3] = 103'); + assert(*result[4] == IntegerTrait::new(14, false), 'result[4] = 14'); + assert(*result[5] == IntegerTrait::new(105, false), 'result[5] = 105'); + assert(*result[6] == IntegerTrait::new(16, false), 'result[6] = 16'); + assert(*result[7] == IntegerTrait::new(107, false), 'result[7] = 107'); } } @@ -493,14 +493,14 @@ mod tensor_3D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(0, false), 'result[1] = 0'); - assert(*result.at(2) == IntegerTrait::new(0, false), 'result[2] = 0'); - assert(*result.at(3) == IntegerTrait::new(0, false), 'result[3] = 0'); - assert(*result.at(4) == IntegerTrait::new(0, false), 'result[4] = 0'); - assert(*result.at(5) == IntegerTrait::new(0, false), 'result[5] = 0'); - assert(*result.at(6) == IntegerTrait::new(0, false), 'result[6] = 0'); - assert(*result.at(7) == IntegerTrait::new(0, false), 'result[7] = 0'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(0, false), 'result[1] = 0'); + assert(*result[2] == IntegerTrait::new(0, false), 'result[2] = 0'); + assert(*result[3] == IntegerTrait::new(0, false), 'result[3] = 0'); + assert(*result[4] == IntegerTrait::new(0, false), 'result[4] = 0'); + assert(*result[5] == IntegerTrait::new(0, false), 'result[5] = 0'); + assert(*result[6] == IntegerTrait::new(0, false), 'result[6] = 0'); + assert(*result[7] == IntegerTrait::new(0, false), 'result[7] = 0'); } #[test] @@ -520,14 +520,14 @@ mod tensor_3D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); - assert(*result.at(2) == IntegerTrait::new(1, false), 'result[2] = 1'); - assert(*result.at(3) == IntegerTrait::new(2, false), 'result[3] = 2'); - assert(*result.at(4) == IntegerTrait::new(4, false), 'result[4] = 4'); - assert(*result.at(5) == IntegerTrait::new(5, false), 'result[5] = 5'); - assert(*result.at(6) == IntegerTrait::new(5, false), 'result[6] = 5'); - assert(*result.at(7) == IntegerTrait::new(6, false), 'result[7] = 6'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result[2] == IntegerTrait::new(1, false), 'result[2] = 1'); + assert(*result[3] == IntegerTrait::new(2, false), 'result[3] = 2'); + assert(*result[4] == IntegerTrait::new(4, false), 'result[4] = 4'); + assert(*result[5] == IntegerTrait::new(5, false), 'result[5] = 5'); + assert(*result[6] == IntegerTrait::new(5, false), 'result[6] = 5'); + assert(*result[7] == IntegerTrait::new(6, false), 'result[7] = 6'); } } @@ -549,14 +549,14 @@ mod tensor_3D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); - assert(*result.at(2) == IntegerTrait::new(4, false), 'result[2] = 4'); - assert(*result.at(3) == IntegerTrait::new(9, false), 'result[3] = 9'); - assert(*result.at(4) == IntegerTrait::new(16, false), 'result[4] = 16'); - assert(*result.at(5) == IntegerTrait::new(25, false), 'result[5] = 25'); - assert(*result.at(6) == IntegerTrait::new(36, false), 'result[6] = 36'); - assert(*result.at(7) == IntegerTrait::new(49, false), 'result[7] = 49'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result[2] == IntegerTrait::new(4, false), 'result[2] = 4'); + assert(*result[3] == IntegerTrait::new(9, false), 'result[3] = 9'); + assert(*result[4] == IntegerTrait::new(16, false), 'result[4] = 16'); + assert(*result[5] == IntegerTrait::new(25, false), 'result[5] = 25'); + assert(*result[6] == IntegerTrait::new(36, false), 'result[6] = 36'); + assert(*result[7] == IntegerTrait::new(49, false), 'result[7] = 49'); } #[test] @@ -576,14 +576,14 @@ mod tensor_3D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(0, false), 'result[0] = 0'); - assert(*result.at(1) == IntegerTrait::new(10, false), 'result[1] = 10'); - assert(*result.at(2) == IntegerTrait::new(200, false), 'result[2] = 200'); - assert(*result.at(3) == IntegerTrait::new(300, false), 'result[3] = 300'); - assert(*result.at(4) == IntegerTrait::new(40, false), 'result[4] = 40'); - assert(*result.at(5) == IntegerTrait::new(50, false), 'result[5] = 50'); - assert(*result.at(6) == IntegerTrait::new(600, false), 'result[6] = 600'); - assert(*result.at(7) == IntegerTrait::new(700, false), 'result[7] = 700'); + assert(*result[0] == IntegerTrait::new(0, false), 'result[0] = 0'); + assert(*result[1] == IntegerTrait::new(10, false), 'result[1] = 10'); + assert(*result[2] == IntegerTrait::new(200, false), 'result[2] = 200'); + assert(*result[3] == IntegerTrait::new(300, false), 'result[3] = 300'); + assert(*result[4] == IntegerTrait::new(40, false), 'result[4] = 40'); + assert(*result[5] == IntegerTrait::new(50, false), 'result[5] = 50'); + assert(*result[6] == IntegerTrait::new(600, false), 'result[6] = 600'); + assert(*result[7] == IntegerTrait::new(700, false), 'result[7] = 700'); } } @@ -618,14 +618,14 @@ mod tensor_3D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(1, false), 'result[0] = 1'); - assert(*result.at(1) == IntegerTrait::new(1, false), 'result[1] = 1'); - assert(*result.at(2) == IntegerTrait::new(1, false), 'result[2] = 1'); - assert(*result.at(3) == IntegerTrait::new(1, false), 'result[3] = 1'); - assert(*result.at(4) == IntegerTrait::new(1, false), 'result[4] = 1'); - assert(*result.at(5) == IntegerTrait::new(1, false), 'result[5] = 1'); - assert(*result.at(6) == IntegerTrait::new(1, false), 'result[6] = 1'); - assert(*result.at(7) == IntegerTrait::new(1, false), 'result[7] = 1'); + assert(*result[0] == IntegerTrait::new(1, false), 'result[0] = 1'); + assert(*result[1] == IntegerTrait::new(1, false), 'result[1] = 1'); + assert(*result[2] == IntegerTrait::new(1, false), 'result[2] = 1'); + assert(*result[3] == IntegerTrait::new(1, false), 'result[3] = 1'); + assert(*result[4] == IntegerTrait::new(1, false), 'result[4] = 1'); + assert(*result[5] == IntegerTrait::new(1, false), 'result[5] = 1'); + assert(*result[6] == IntegerTrait::new(1, false), 'result[6] = 1'); + assert(*result[7] == IntegerTrait::new(1, false), 'result[7] = 1'); } #[test] @@ -659,14 +659,14 @@ mod tensor_3D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == IntegerTrait::new(10, false), 'result[0] = 10'); - assert(*result.at(1) == IntegerTrait::new(20, false), 'result[1] = 20'); - assert(*result.at(2) == IntegerTrait::new(3, false), 'result[2] = 3'); - assert(*result.at(3) == IntegerTrait::new(4, false), 'result[3] = 4'); - assert(*result.at(4) == IntegerTrait::new(50, false), 'result[4] = 50'); - assert(*result.at(5) == IntegerTrait::new(60, false), 'result[5] = 60'); - assert(*result.at(6) == IntegerTrait::new(7, false), 'result[6] = 7'); - assert(*result.at(7) == IntegerTrait::new(8, false), 'result[7] = 8'); + assert(*result[0] == IntegerTrait::new(10, false), 'result[0] = 10'); + assert(*result[1] == IntegerTrait::new(20, false), 'result[1] = 20'); + assert(*result[2] == IntegerTrait::new(3, false), 'result[2] = 3'); + assert(*result[3] == IntegerTrait::new(4, false), 'result[3] = 4'); + assert(*result[4] == IntegerTrait::new(50, false), 'result[4] = 50'); + assert(*result[5] == IntegerTrait::new(60, false), 'result[5] = 60'); + assert(*result[6] == IntegerTrait::new(7, false), 'result[6] = 7'); + assert(*result[7] == IntegerTrait::new(8, false), 'result[7] = 8'); } } } diff --git a/src/tests/operators/tensor/math/arithmetic/arithmetic_u32_test.cairo b/src/tests/operators/tensor/math/arithmetic/arithmetic_u32_test.cairo index b96c6fe02..487c91605 100644 --- a/src/tests/operators/tensor/math/arithmetic/arithmetic_u32_test.cairo +++ b/src/tests/operators/tensor/math/arithmetic/arithmetic_u32_test.cairo @@ -18,9 +18,9 @@ mod tensor_1D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == 0_u32, 'result[0] = 0'); - assert(*result.at(1) == 2_u32, 'result[1] = 2'); - assert(*result.at(2) == 4_u32, 'result[2] = 4'); + assert(*result[0] == 0_u32, 'result[0] = 0'); + assert(*result[1] == 2_u32, 'result[1] = 2'); + assert(*result[2] == 4_u32, 'result[2] = 4'); } } @@ -40,9 +40,9 @@ mod tensor_1D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == 0_u32, 'result[0] = 0'); - assert(*result.at(1) == 0_u32, 'result[1] = 0'); - assert(*result.at(2) == 0_u32, 'result[2] = 0'); + assert(*result[0] == 0_u32, 'result[0] = 0'); + assert(*result[1] == 0_u32, 'result[1] = 0'); + assert(*result[2] == 0_u32, 'result[2] = 0'); } } @@ -62,9 +62,9 @@ mod tensor_1D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == 0_u32, 'result[0] = 0'); - assert(*result.at(1) == 1_u32, 'result[1] = 1'); - assert(*result.at(2) == 4_u32, 'result[2] = 4'); + assert(*result[0] == 0_u32, 'result[0] = 0'); + assert(*result[1] == 1_u32, 'result[1] = 1'); + assert(*result[2] == 4_u32, 'result[2] = 4'); } } @@ -91,8 +91,8 @@ mod tensor_1D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == 1, 'result[0] = 1'); - assert(*result.at(1) == 1, 'result[1] = 1'); + assert(*result[0] == 1, 'result[0] = 1'); + assert(*result[1] == 1, 'result[1] = 1'); } } } @@ -118,10 +118,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 2, 'result[1] = 2'); - assert(*result.at(2) == 4, 'result[2] = 4'); - assert(*result.at(3) == 6, 'result[3] = 6'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 2, 'result[1] = 2'); + assert(*result[2] == 4, 'result[2] = 4'); + assert(*result[3] == 6, 'result[3] = 6'); } #[test] @@ -139,10 +139,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == 10, 'result[0] = 10'); - assert(*result.at(1) == 101, 'result[1] = 101'); - assert(*result.at(2) == 12, 'result[2] = 12'); - assert(*result.at(3) == 103, 'result[3] = 103'); + assert(*result[0] == 10, 'result[0] = 10'); + assert(*result[1] == 101, 'result[1] = 101'); + assert(*result[2] == 12, 'result[2] = 12'); + assert(*result[3] == 103, 'result[3] = 103'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -155,10 +155,10 @@ mod tensor_2D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == 10, 'result[0] = 10'); - assert(*result.at(1) == 11, 'result[1] = 11'); - assert(*result.at(2) == 102, 'result[2] = 102'); - assert(*result.at(3) == 103, 'result[3] = 103'); + assert(*result[0] == 10, 'result[0] = 10'); + assert(*result[1] == 11, 'result[1] = 11'); + assert(*result[2] == 102, 'result[2] = 102'); + assert(*result[3] == 103, 'result[3] = 103'); } } @@ -179,10 +179,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 0, 'result[1] = 0'); - assert(*result.at(2) == 0, 'result[2] = 0'); - assert(*result.at(3) == 0, 'result[3] = 0'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 0, 'result[1] = 0'); + assert(*result[2] == 0, 'result[2] = 0'); + assert(*result[3] == 0, 'result[3] = 0'); } #[test] @@ -200,10 +200,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 0, 'result[1] = 0'); - assert(*result.at(2) == 2, 'result[2] = 2'); - assert(*result.at(3) == 2, 'result[3] = 2'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 0, 'result[1] = 0'); + assert(*result[2] == 2, 'result[2] = 2'); + assert(*result[3] == 2, 'result[3] = 2'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -216,10 +216,10 @@ mod tensor_2D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 1, 'result[1] = 1'); - assert(*result.at(2) == 1, 'result[2] = 1'); - assert(*result.at(3) == 2, 'result[3] = 2'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 1, 'result[1] = 1'); + assert(*result[2] == 1, 'result[2] = 1'); + assert(*result[3] == 2, 'result[3] = 2'); } } @@ -240,10 +240,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 1, 'result[1] = 1'); - assert(*result.at(2) == 4, 'result[2] = 4'); - assert(*result.at(3) == 9, 'result[3] = 9'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 1, 'result[1] = 1'); + assert(*result[2] == 4, 'result[2] = 4'); + assert(*result[3] == 9, 'result[3] = 9'); } #[test] @@ -261,10 +261,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 100, 'result[1] = 100'); - assert(*result.at(2) == 20, 'result[2] = 20'); - assert(*result.at(3) == 300, 'result[3] = 300'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 100, 'result[1] = 100'); + assert(*result[2] == 20, 'result[2] = 20'); + assert(*result[3] == 300, 'result[3] = 300'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -277,10 +277,10 @@ mod tensor_2D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 10, 'result[1] = 10'); - assert(*result.at(2) == 200, 'result[2] = 200'); - assert(*result.at(3) == 300, 'result[3] = 300'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 10, 'result[1] = 10'); + assert(*result[2] == 200, 'result[2] = 200'); + assert(*result[3] == 300, 'result[3] = 300'); } } @@ -310,10 +310,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == 1, 'result[0] = 1'); - assert(*result.at(1) == 1, 'result[1] = 1'); - assert(*result.at(2) == 1, 'result[2] = 1'); - assert(*result.at(3) == 1, 'result[3] = 1'); + assert(*result[0] == 1, 'result[0] = 1'); + assert(*result[1] == 1, 'result[1] = 1'); + assert(*result[2] == 1, 'result[2] = 1'); + assert(*result[3] == 1, 'result[3] = 1'); } #[test] @@ -341,10 +341,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == 10, 'result[0] = 10'); - assert(*result.at(1) == 2, 'result[1] = 2'); - assert(*result.at(2) == 30, 'result[2] = 30'); - assert(*result.at(3) == 4, 'result[3] = 4'); + assert(*result[0] == 10, 'result[0] = 10'); + assert(*result[1] == 2, 'result[1] = 2'); + assert(*result[2] == 30, 'result[2] = 30'); + assert(*result[3] == 4, 'result[3] = 4'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -357,10 +357,10 @@ mod tensor_2D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == 10, 'result[0] = 10'); - assert(*result.at(1) == 20, 'result[1] = 20'); - assert(*result.at(2) == 3, 'result[2] = 3'); - assert(*result.at(3) == 4, 'result[3] = 4'); + assert(*result[0] == 10, 'result[0] = 10'); + assert(*result[1] == 20, 'result[1] = 20'); + assert(*result[2] == 3, 'result[2] = 3'); + assert(*result[3] == 4, 'result[3] = 4'); } } } @@ -386,14 +386,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 2, 'result[1] = 2'); - assert(*result.at(2) == 4, 'result[2] = 4'); - assert(*result.at(3) == 6, 'result[3] = 6'); - assert(*result.at(4) == 8, 'result[4] = 8'); - assert(*result.at(5) == 10, 'result[5] = 10'); - assert(*result.at(6) == 12, 'result[6] = 12'); - assert(*result.at(7) == 14, 'result[7] = 14'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 2, 'result[1] = 2'); + assert(*result[2] == 4, 'result[2] = 4'); + assert(*result[3] == 6, 'result[3] = 6'); + assert(*result[4] == 8, 'result[4] = 8'); + assert(*result[5] == 10, 'result[5] = 10'); + assert(*result[6] == 12, 'result[6] = 12'); + assert(*result[7] == 14, 'result[7] = 14'); } #[test] @@ -413,14 +413,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == 10, 'result[0] = 10'); - assert(*result.at(1) == 11, 'result[1] = 11'); - assert(*result.at(2) == 102, 'result[2] = 102'); - assert(*result.at(3) == 103, 'result[3] = 103'); - assert(*result.at(4) == 14, 'result[4] = 14'); - assert(*result.at(5) == 15, 'result[5] = 15'); - assert(*result.at(6) == 106, 'result[6] = 106'); - assert(*result.at(7) == 107, 'result[7] = 107'); + assert(*result[0] == 10, 'result[0] = 10'); + assert(*result[1] == 11, 'result[1] = 11'); + assert(*result[2] == 102, 'result[2] = 102'); + assert(*result[3] == 103, 'result[3] = 103'); + assert(*result[4] == 14, 'result[4] = 14'); + assert(*result[5] == 15, 'result[5] = 15'); + assert(*result[6] == 106, 'result[6] = 106'); + assert(*result[7] == 107, 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(2); @@ -434,14 +434,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == 10, 'result[0] = 10'); - assert(*result.at(1) == 11, 'result[1] = 11'); - assert(*result.at(2) == 12, 'result[2] = 12'); - assert(*result.at(3) == 13, 'result[3] = 13'); - assert(*result.at(4) == 104, 'result[4] = 104'); - assert(*result.at(5) == 105, 'result[5] = 105'); - assert(*result.at(6) == 106, 'result[6] = 106'); - assert(*result.at(7) == 107, 'result[7] = 107'); + assert(*result[0] == 10, 'result[0] = 10'); + assert(*result[1] == 11, 'result[1] = 11'); + assert(*result[2] == 12, 'result[2] = 12'); + assert(*result[3] == 13, 'result[3] = 13'); + assert(*result[4] == 104, 'result[4] = 104'); + assert(*result[5] == 105, 'result[5] = 105'); + assert(*result[6] == 106, 'result[6] = 106'); + assert(*result[7] == 107, 'result[7] = 107'); let mut sizes = ArrayTrait::new(); sizes.append(1); @@ -455,14 +455,14 @@ mod tensor_3D { let result = (tensor_1 + tensor_2).data; - assert(*result.at(0) == 10, 'result[0] = 10'); - assert(*result.at(1) == 101, 'result[1] = 101'); - assert(*result.at(2) == 12, 'result[2] = 12'); - assert(*result.at(3) == 103, 'result[3] = 103'); - assert(*result.at(4) == 14, 'result[4] = 14'); - assert(*result.at(5) == 105, 'result[5] = 105'); - assert(*result.at(6) == 16, 'result[6] = 16'); - assert(*result.at(7) == 107, 'result[7] = 107'); + assert(*result[0] == 10, 'result[0] = 10'); + assert(*result[1] == 101, 'result[1] = 101'); + assert(*result[2] == 12, 'result[2] = 12'); + assert(*result[3] == 103, 'result[3] = 103'); + assert(*result[4] == 14, 'result[4] = 14'); + assert(*result[5] == 105, 'result[5] = 105'); + assert(*result[6] == 16, 'result[6] = 16'); + assert(*result[7] == 107, 'result[7] = 107'); } } @@ -483,14 +483,14 @@ mod tensor_3D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 0, 'result[1] = 0'); - assert(*result.at(2) == 0, 'result[2] = 0'); - assert(*result.at(3) == 0, 'result[3] = 0'); - assert(*result.at(4) == 0, 'result[4] = 0'); - assert(*result.at(5) == 0, 'result[5] = 0'); - assert(*result.at(6) == 0, 'result[6] = 0'); - assert(*result.at(7) == 0, 'result[7] = 0'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 0, 'result[1] = 0'); + assert(*result[2] == 0, 'result[2] = 0'); + assert(*result[3] == 0, 'result[3] = 0'); + assert(*result[4] == 0, 'result[4] = 0'); + assert(*result[5] == 0, 'result[5] = 0'); + assert(*result[6] == 0, 'result[6] = 0'); + assert(*result[7] == 0, 'result[7] = 0'); } #[test] @@ -510,14 +510,14 @@ mod tensor_3D { let result = (tensor_1 - tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 1, 'result[1] = 1'); - assert(*result.at(2) == 1, 'result[2] = 1'); - assert(*result.at(3) == 2, 'result[3] = 2'); - assert(*result.at(4) == 4, 'result[4] = 4'); - assert(*result.at(5) == 5, 'result[5] = 5'); - assert(*result.at(6) == 5, 'result[6] = 5'); - assert(*result.at(7) == 6, 'result[7] = 6'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 1, 'result[1] = 1'); + assert(*result[2] == 1, 'result[2] = 1'); + assert(*result[3] == 2, 'result[3] = 2'); + assert(*result[4] == 4, 'result[4] = 4'); + assert(*result[5] == 5, 'result[5] = 5'); + assert(*result[6] == 5, 'result[6] = 5'); + assert(*result[7] == 6, 'result[7] = 6'); } } @@ -538,14 +538,14 @@ mod tensor_3D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 1, 'result[1] = 1'); - assert(*result.at(2) == 4, 'result[2] = 4'); - assert(*result.at(3) == 9, 'result[3] = 9'); - assert(*result.at(4) == 16, 'result[4] = 16'); - assert(*result.at(5) == 25, 'result[5] = 25'); - assert(*result.at(6) == 36, 'result[6] = 36'); - assert(*result.at(7) == 49, 'result[7] = 49'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 1, 'result[1] = 1'); + assert(*result[2] == 4, 'result[2] = 4'); + assert(*result[3] == 9, 'result[3] = 9'); + assert(*result[4] == 16, 'result[4] = 16'); + assert(*result[5] == 25, 'result[5] = 25'); + assert(*result[6] == 36, 'result[6] = 36'); + assert(*result[7] == 49, 'result[7] = 49'); } #[test] @@ -565,14 +565,14 @@ mod tensor_3D { let result = (tensor_1 * tensor_2).data; - assert(*result.at(0) == 0, 'result[0] = 0'); - assert(*result.at(1) == 10, 'result[1] = 10'); - assert(*result.at(2) == 200, 'result[2] = 200'); - assert(*result.at(3) == 300, 'result[3] = 300'); - assert(*result.at(4) == 40, 'result[4] = 40'); - assert(*result.at(5) == 50, 'result[5] = 50'); - assert(*result.at(6) == 600, 'result[6] = 600'); - assert(*result.at(7) == 700, 'result[7] = 700'); + assert(*result[0] == 0, 'result[0] = 0'); + assert(*result[1] == 10, 'result[1] = 10'); + assert(*result[2] == 200, 'result[2] = 200'); + assert(*result[3] == 300, 'result[3] = 300'); + assert(*result[4] == 40, 'result[4] = 40'); + assert(*result[5] == 50, 'result[5] = 50'); + assert(*result[6] == 600, 'result[6] = 600'); + assert(*result[7] == 700, 'result[7] = 700'); } } @@ -606,14 +606,14 @@ mod tensor_3D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == 1, 'result[0] = 1'); - assert(*result.at(1) == 1, 'result[1] = 1'); - assert(*result.at(2) == 1, 'result[2] = 1'); - assert(*result.at(3) == 1, 'result[3] = 1'); - assert(*result.at(4) == 1, 'result[4] = 1'); - assert(*result.at(5) == 1, 'result[5] = 1'); - assert(*result.at(6) == 1, 'result[6] = 1'); - assert(*result.at(7) == 1, 'result[7] = 1'); + assert(*result[0] == 1, 'result[0] = 1'); + assert(*result[1] == 1, 'result[1] = 1'); + assert(*result[2] == 1, 'result[2] = 1'); + assert(*result[3] == 1, 'result[3] = 1'); + assert(*result[4] == 1, 'result[4] = 1'); + assert(*result[5] == 1, 'result[5] = 1'); + assert(*result[6] == 1, 'result[6] = 1'); + assert(*result[7] == 1, 'result[7] = 1'); } #[test] @@ -647,14 +647,14 @@ mod tensor_3D { let result = (tensor_1 / tensor_2).data; - assert(*result.at(0) == 10, 'result[0] = 10'); - assert(*result.at(1) == 20, 'result[1] = 20'); - assert(*result.at(2) == 3, 'result[2] = 3'); - assert(*result.at(3) == 4, 'result[3] = 4'); - assert(*result.at(4) == 50, 'result[4] = 50'); - assert(*result.at(5) == 60, 'result[5] = 60'); - assert(*result.at(6) == 7, 'result[6] = 7'); - assert(*result.at(7) == 8, 'result[7] = 8'); + assert(*result[0] == 10, 'result[0] = 10'); + assert(*result[1] == 20, 'result[1] = 20'); + assert(*result[2] == 3, 'result[2] = 3'); + assert(*result[3] == 4, 'result[3] = 4'); + assert(*result[4] == 50, 'result[4] = 50'); + assert(*result[5] == 60, 'result[5] = 60'); + assert(*result[6] == 7, 'result[6] = 7'); + assert(*result[7] == 8, 'result[7] = 8'); } } } diff --git a/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo b/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo index 2def81007..ab3bfe437 100644 --- a/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp16x16_test.cairo @@ -23,10 +23,10 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data[3] == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } } @@ -58,10 +58,10 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data[3] == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } } @@ -100,14 +100,14 @@ mod tensor_3D { let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.data[3] == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); + assert(*result.data[4] == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.data[5] == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.data[6] == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data[7] == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } } diff --git a/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo b/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo index 935bd0702..019440556 100644 --- a/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/ceil/ceil_fp_test/ceil_fp8x23_test.cairo @@ -23,10 +23,10 @@ mod tensor_1D { let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data[3] == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } } @@ -57,10 +57,10 @@ mod tensor_2D { let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); // 1 + assert(*result.data[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); // 12 + assert(*result.data[3] == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); // -11 assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } } @@ -99,14 +99,14 @@ mod tensor_3D { let tensor = TensorTrait::::new(sizes.span(), arr.span(), Option::Some(extra)); let result = tensor.ceil(); - assert(*result.data.at(0) == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); - assert(*result.data.at(1) == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); - assert(*result.data.at(2) == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); - assert(*result.data.at(3) == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); - assert(*result.data.at(4) == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); - assert(*result.data.at(5) == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); - assert(*result.data.at(6) == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); - assert(*result.data.at(7) == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); + assert(*result.data[0] == FixedTrait::new_unscaled(0, false), 'result[0] = 0'); + assert(*result.data[1] == FixedTrait::new_unscaled(1, false), 'result[1] = 1'); + assert(*result.data[2] == FixedTrait::new_unscaled(12, false), 'result[2] = 12'); + assert(*result.data[3] == FixedTrait::new_unscaled(11, true), 'result[3] = -11'); + assert(*result.data[4] == FixedTrait::new_unscaled(1, false), 'result[4] = 1'); + assert(*result.data[5] == FixedTrait::new_unscaled(0, false), 'result[5] = 0'); + assert(*result.data[6] == FixedTrait::new_unscaled(2, false), 'result[6] = 2'); + assert(*result.data[7] == FixedTrait::new_unscaled(1, true), 'result[7] = -1'); assert(result.data.len() == tensor.data.len(), 'tensor length mismatch'); } } diff --git a/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp16x16_test.cairo b/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp16x16_test.cairo index f5de9ca26..738e6cf1f 100644 --- a/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp16x16_test.cairo @@ -33,9 +33,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 1, 'result[2] = 1'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -88,15 +88,15 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); + assert(*result.data[4] == 1, 'result[4] = 1'); + assert(*result.data[5] == 1, 'result[5] = 1'); + assert(*result.data[6] == 0, 'result[6] = 0'); + assert(*result.data[7] == 0, 'result[7] = 0'); + assert(*result.data[8] == 0, 'result[8] = 0'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -137,33 +137,33 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); + assert(*result_b.data[8] == 0, 'result[8] = 0'); + assert(*result_b.data[9] == 0, 'result[9] = 0'); + assert(*result_b.data[10] == 0, 'result[10] = 0'); + assert(*result_b.data[11] == 0, 'result[11] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } } @@ -214,14 +214,14 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); + assert(*result.data[4] == 1, 'result[4] = 1'); + assert(*result.data[5] == 1, 'result[5] = 1'); + assert(*result.data[6] == 0, 'result[6] = 0'); + assert(*result.data[7] == 0, 'result[7] = 0'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -259,25 +259,25 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } } diff --git a/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp8x23_test.cairo b/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp8x23_test.cairo index a824347c7..1ed18e5f3 100644 --- a/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/equal/equal_fp_test/equal_fp8x23_test.cairo @@ -36,9 +36,9 @@ mod tensor_1D { ); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 1, 'result[2] = 1'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -97,15 +97,15 @@ mod tensor_2D { ); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); + assert(*result.data[4] == 1, 'result[4] = 1'); + assert(*result.data[5] == 1, 'result[5] = 1'); + assert(*result.data[6] == 0, 'result[6] = 0'); + assert(*result.data[7] == 0, 'result[7] = 0'); + assert(*result.data[8] == 0, 'result[8] = 0'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -150,33 +150,33 @@ mod tensor_2D { ); let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); + assert(*result_b.data[8] == 0, 'result[8] = 0'); + assert(*result_b.data[9] == 0, 'result[9] = 0'); + assert(*result_b.data[10] == 0, 'result[10] = 0'); + assert(*result_b.data[11] == 0, 'result[11] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } } @@ -231,14 +231,14 @@ mod tensor_3D { ); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); + assert(*result.data[4] == 1, 'result[4] = 1'); + assert(*result.data[5] == 1, 'result[5] = 1'); + assert(*result.data[6] == 0, 'result[6] = 0'); + assert(*result.data[7] == 0, 'result[7] = 0'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -280,25 +280,25 @@ mod tensor_3D { ); let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } } diff --git a/src/tests/operators/tensor/math/equal/equal_i32_test.cairo b/src/tests/operators/tensor/math/equal/equal_i32_test.cairo index ce62fcf89..0f986ca08 100644 --- a/src/tests/operators/tensor/math/equal/equal_i32_test.cairo +++ b/src/tests/operators/tensor/math/equal/equal_i32_test.cairo @@ -31,9 +31,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 1, 'result[2] = 1'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 1, 'result[2] = 1'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -85,15 +85,15 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); + assert(*result.data[4] == 1, 'result[4] = 1'); + assert(*result.data[5] == 1, 'result[5] = 1'); + assert(*result.data[6] == 0, 'result[6] = 0'); + assert(*result.data[7] == 0, 'result[7] = 0'); + assert(*result.data[8] == 0, 'result[8] = 0'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -134,33 +134,33 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); + assert(*result_b.data[8] == 0, 'result[8] = 0'); + assert(*result_b.data[9] == 0, 'result[9] = 0'); + assert(*result_b.data[10] == 0, 'result[10] = 0'); + assert(*result_b.data[11] == 0, 'result[11] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } } @@ -210,14 +210,14 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); + assert(*result.data[4] == 1, 'result[4] = 1'); + assert(*result.data[5] == 1, 'result[5] = 1'); + assert(*result.data[6] == 0, 'result[6] = 0'); + assert(*result.data[7] == 0, 'result[7] = 0'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -255,25 +255,25 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } } diff --git a/src/tests/operators/tensor/math/equal/equal_u32_test.cairo b/src/tests/operators/tensor/math/equal/equal_u32_test.cairo index 88afbd0a5..1d3150489 100644 --- a/src/tests/operators/tensor/math/equal/equal_u32_test.cairo +++ b/src/tests/operators/tensor/math/equal/equal_u32_test.cairo @@ -82,15 +82,15 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); - assert(*result.data.at(8) == 0, 'result[8] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); + assert(*result.data[4] == 1, 'result[4] = 1'); + assert(*result.data[5] == 1, 'result[5] = 1'); + assert(*result.data[6] == 0, 'result[6] = 0'); + assert(*result.data[7] == 0, 'result[7] = 0'); + assert(*result.data[8] == 0, 'result[8] = 0'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -131,33 +131,33 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); + assert(*result_b.data[8] == 0, 'result[8] = 0'); + assert(*result_b.data[9] == 0, 'result[9] = 0'); + assert(*result_b.data[10] == 0, 'result[10] = 0'); + assert(*result_b.data[11] == 0, 'result[11] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } } @@ -206,14 +206,14 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result = tensor_a.eq(@tensor_b); - assert(*result.data.at(0) == 0, 'result[0] = 0'); - assert(*result.data.at(1) == 0, 'result[1] = 0'); - assert(*result.data.at(2) == 0, 'result[2] = 0'); - assert(*result.data.at(3) == 0, 'result[3] = 0'); - assert(*result.data.at(4) == 1, 'result[4] = 1'); - assert(*result.data.at(5) == 1, 'result[5] = 1'); - assert(*result.data.at(6) == 0, 'result[6] = 0'); - assert(*result.data.at(7) == 0, 'result[7] = 0'); + assert(*result.data[0] == 0, 'result[0] = 0'); + assert(*result.data[1] == 0, 'result[1] = 0'); + assert(*result.data[2] == 0, 'result[2] = 0'); + assert(*result.data[3] == 0, 'result[3] = 0'); + assert(*result.data[4] == 1, 'result[4] = 1'); + assert(*result.data[5] == 1, 'result[5] = 1'); + assert(*result.data[6] == 0, 'result[6] = 0'); + assert(*result.data[7] == 0, 'result[7] = 0'); assert(result.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -251,25 +251,25 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.eq(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.eq(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } } diff --git a/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp16x16_test.cairo b/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp16x16_test.cairo index 8556ec9e7..149769b73 100644 --- a/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp16x16_test.cairo @@ -32,9 +32,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -87,28 +87,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -149,34 +149,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); + assert(*result_b.data[9] == 1, 'result[9] = 1'); + assert(*result_b.data[10] == 1, 'result[10] = 1'); + assert(*result_b.data[11] == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -229,26 +229,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -286,26 +286,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 1, 'result[2] = 0'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp8x23_test.cairo b/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp8x23_test.cairo index 4cdead3dd..a4b3dc462 100644 --- a/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/greater/greater_fp_test/greater_fp8x23_test.cairo @@ -32,9 +32,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -88,28 +88,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -150,34 +150,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); + assert(*result_b.data[9] == 1, 'result[9] = 1'); + assert(*result_b.data[10] == 1, 'result[10] = 1'); + assert(*result_b.data[11] == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -230,26 +230,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -287,26 +287,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 1, 'result[2] = 0'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/greater/greater_i32_test.cairo b/src/tests/operators/tensor/math/greater/greater_i32_test.cairo index 2dc3fd5aa..854d8cee4 100644 --- a/src/tests/operators/tensor/math/greater/greater_i32_test.cairo +++ b/src/tests/operators/tensor/math/greater/greater_i32_test.cairo @@ -31,9 +31,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -87,28 +87,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -149,34 +149,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); + assert(*result_b.data[9] == 1, 'result[9] = 1'); + assert(*result_b.data[10] == 1, 'result[10] = 1'); + assert(*result_b.data[11] == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -228,26 +228,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -285,26 +285,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/greater/greater_u32_test.cairo b/src/tests/operators/tensor/math/greater/greater_u32_test.cairo index add8a5bf4..d7a456ee8 100644 --- a/src/tests/operators/tensor/math/greater/greater_u32_test.cairo +++ b/src/tests/operators/tensor/math/greater/greater_u32_test.cairo @@ -29,16 +29,16 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -89,28 +89,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -151,34 +151,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); + assert(*result_b.data[9] == 1, 'result[9] = 1'); + assert(*result_b.data[10] == 1, 'result[10] = 1'); + assert(*result_b.data[11] == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -227,26 +227,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -284,25 +284,25 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo index ccb842082..d5db639a3 100644 --- a/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp16x16_test.cairo @@ -33,9 +33,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -91,28 +91,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -153,34 +153,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); + assert(*result_b.data[9] == 1, 'result[9] = 1'); + assert(*result_b.data[10] == 1, 'result[10] = 1'); + assert(*result_b.data[11] == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -234,26 +234,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -291,26 +291,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo index f51426d7f..25c7bad71 100644 --- a/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/greater_equal/greater_equal_fp_test/greater_equal_fp8x23_test.cairo @@ -37,9 +37,9 @@ mod tensor_1D { ); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -99,28 +99,28 @@ mod tensor_2D { ); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -165,34 +165,34 @@ mod tensor_2D { ); let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); + assert(*result_b.data[9] == 1, 'result[9] = 1'); + assert(*result_b.data[10] == 1, 'result[10] = 1'); + assert(*result_b.data[11] == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -250,26 +250,26 @@ mod tensor_3D { ); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -311,26 +311,26 @@ mod tensor_3D { ); let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/greater_equal/greater_equal_i32_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_i32_test.cairo index 4039e559e..866a28981 100644 --- a/src/tests/operators/tensor/math/greater_equal/greater_equal_i32_test.cairo +++ b/src/tests/operators/tensor/math/greater_equal/greater_equal_i32_test.cairo @@ -31,9 +31,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -87,28 +87,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -149,34 +149,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); + assert(*result_b.data[9] == 1, 'result[9] = 1'); + assert(*result_b.data[10] == 1, 'result[10] = 1'); + assert(*result_b.data[11] == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -228,26 +228,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -285,26 +285,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/greater_equal/greater_equal_u32_test.cairo b/src/tests/operators/tensor/math/greater_equal/greater_equal_u32_test.cairo index 80ef9ec8d..4104fdd9b 100644 --- a/src/tests/operators/tensor/math/greater_equal/greater_equal_u32_test.cairo +++ b/src/tests/operators/tensor/math/greater_equal/greater_equal_u32_test.cairo @@ -29,16 +29,16 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -89,28 +89,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -151,34 +151,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); - assert(*result_a.data.at(8) == 0, 'result[8] = 0'); - assert(*result_a.data.at(9) == 0, 'result[9] = 0'); - assert(*result_a.data.at(10) == 0, 'result[10] = 0'); - assert(*result_a.data.at(11) == 0, 'result[11] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); + assert(*result_a.data[8] == 0, 'result[8] = 0'); + assert(*result_a.data[9] == 0, 'result[9] = 0'); + assert(*result_a.data[10] == 0, 'result[10] = 0'); + assert(*result_a.data[11] == 0, 'result[11] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); - assert(*result_b.data.at(8) == 1, 'result[8] = 1'); - assert(*result_b.data.at(9) == 1, 'result[9] = 1'); - assert(*result_b.data.at(10) == 1, 'result[10] = 1'); - assert(*result_b.data.at(11) == 1, 'result[11] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); + assert(*result_b.data[8] == 1, 'result[8] = 1'); + assert(*result_b.data[9] == 1, 'result[9] = 1'); + assert(*result_b.data[10] == 1, 'result[10] = 1'); + assert(*result_b.data[11] == 1, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -227,26 +227,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.greater_equal(@tensor_b); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.greater_equal(@tensor_a); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); - assert(*result_b.data.at(7) == 1, 'result[7] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); + assert(*result_b.data[7] == 1, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -284,25 +284,25 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.greater_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 0, 'result[3] = 0'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 0, 'result[6] = 0'); - assert(*result_a.data.at(7) == 0, 'result[7] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 0, 'result[3] = 0'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 0, 'result[6] = 0'); + assert(*result_a.data[7] == 0, 'result[7] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.greater_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 1, 'result[6] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 1, 'result[6] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/less/less_fp_test/less_fp16x16_test.cairo b/src/tests/operators/tensor/math/less/less_fp_test/less_fp16x16_test.cairo index 7d3237018..867a1aca2 100644 --- a/src/tests/operators/tensor/math/less/less_fp_test/less_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/less/less_fp_test/less_fp16x16_test.cairo @@ -32,9 +32,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -88,28 +88,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -150,34 +150,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); + assert(*result_a.data[9] == 1, 'result[9] = 1'); + assert(*result_a.data[10] == 1, 'result[10] = 1'); + assert(*result_a.data[11] == 1, 'result[11] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); - assert(*result_b.data.at(9) == 0, 'result[9] = 1'); - assert(*result_b.data.at(10) == 0, 'result[10] = 1'); - assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); + assert(*result_b.data[9] == 0, 'result[9] = 1'); + assert(*result_b.data[10] == 0, 'result[10] = 1'); + assert(*result_b.data[11] == 0, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -230,26 +230,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -287,26 +287,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/less/less_fp_test/less_fp8x23_test.cairo b/src/tests/operators/tensor/math/less/less_fp_test/less_fp8x23_test.cairo index 9efe3284e..0f8df3f78 100644 --- a/src/tests/operators/tensor/math/less/less_fp_test/less_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/less/less_fp_test/less_fp8x23_test.cairo @@ -32,9 +32,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -88,28 +88,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -150,34 +150,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); + assert(*result_a.data[9] == 1, 'result[9] = 1'); + assert(*result_a.data[10] == 1, 'result[10] = 1'); + assert(*result_a.data[11] == 1, 'result[11] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); - assert(*result_b.data.at(9) == 0, 'result[9] = 1'); - assert(*result_b.data.at(10) == 0, 'result[10] = 1'); - assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); + assert(*result_b.data[9] == 0, 'result[9] = 1'); + assert(*result_b.data[10] == 0, 'result[10] = 1'); + assert(*result_b.data[11] == 0, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -230,26 +230,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -287,26 +287,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), Option::Some(extra)); let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/less/less_i32_test.cairo b/src/tests/operators/tensor/math/less/less_i32_test.cairo index 9cc413f72..10fd7354c 100644 --- a/src/tests/operators/tensor/math/less/less_i32_test.cairo +++ b/src/tests/operators/tensor/math/less/less_i32_test.cairo @@ -31,9 +31,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -87,28 +87,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -149,34 +149,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); + assert(*result_a.data[9] == 1, 'result[9] = 1'); + assert(*result_a.data[10] == 1, 'result[10] = 1'); + assert(*result_a.data[11] == 1, 'result[11] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); - assert(*result_b.data.at(9) == 0, 'result[9] = 1'); - assert(*result_b.data.at(10) == 0, 'result[10] = 1'); - assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); + assert(*result_b.data[9] == 0, 'result[9] = 1'); + assert(*result_b.data[10] == 0, 'result[10] = 1'); + assert(*result_b.data[11] == 0, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -228,26 +228,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -285,26 +285,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/less/less_u32_test.cairo b/src/tests/operators/tensor/math/less/less_u32_test.cairo index cf6b3c8b8..39a87ecf9 100644 --- a/src/tests/operators/tensor/math/less/less_u32_test.cairo +++ b/src/tests/operators/tensor/math/less/less_u32_test.cairo @@ -29,16 +29,16 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -89,28 +89,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); + assert(*result_b.data[8] == 0, 'result[8] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -151,34 +151,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); + assert(*result_a.data[9] == 1, 'result[9] = 1'); + assert(*result_a.data[10] == 1, 'result[10] = 1'); + assert(*result_a.data[11] == 1, 'result[11] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); + assert(*result_b.data[8] == 0, 'result[8] = 0'); + assert(*result_b.data[9] == 0, 'result[9] = 0'); + assert(*result_b.data[10] == 0, 'result[10] = 0'); + assert(*result_b.data[11] == 0, 'result[11] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -227,26 +227,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 0, 'result[4] = 0'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 0, 'result[4] = 0'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -284,25 +284,25 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less(@tensor_a); - assert(*result_a.data.at(0) == 0, 'result[0] = 0'); - assert(*result_a.data.at(1) == 0, 'result[1] = 0'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 0, 'result[0] = 0'); + assert(*result_a.data[1] == 0, 'result[1] = 0'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less(@tensor_b); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo index 2ed2b5023..751dd0552 100644 --- a/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo +++ b/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp16x16_test.cairo @@ -32,9 +32,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -89,28 +89,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -151,34 +151,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); + assert(*result_a.data[9] == 1, 'result[9] = 1'); + assert(*result_a.data[10] == 1, 'result[10] = 1'); + assert(*result_a.data[11] == 1, 'result[11] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); - assert(*result_b.data.at(9) == 0, 'result[9] = 1'); - assert(*result_b.data.at(10) == 0, 'result[10] = 1'); - assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); + assert(*result_b.data[9] == 0, 'result[9] = 1'); + assert(*result_b.data[10] == 0, 'result[10] = 1'); + assert(*result_b.data[11] == 0, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -231,26 +231,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -288,26 +288,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo index b4b8ff3f5..cd996c709 100644 --- a/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo +++ b/src/tests/operators/tensor/math/less_equal/less_equal_fp_test/less_equal_fp8x23_test.cairo @@ -36,9 +36,9 @@ mod tensor_1D { ); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -97,28 +97,28 @@ mod tensor_2D { ); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -163,34 +163,34 @@ mod tensor_2D { ); let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); + assert(*result_a.data[9] == 1, 'result[9] = 1'); + assert(*result_a.data[10] == 1, 'result[10] = 1'); + assert(*result_a.data[11] == 1, 'result[11] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); - assert(*result_b.data.at(9) == 0, 'result[9] = 1'); - assert(*result_b.data.at(10) == 0, 'result[10] = 1'); - assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); + assert(*result_b.data[9] == 0, 'result[9] = 1'); + assert(*result_b.data[10] == 0, 'result[10] = 1'); + assert(*result_b.data[11] == 0, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -247,26 +247,26 @@ mod tensor_3D { ); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -308,26 +308,26 @@ mod tensor_3D { ); let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/less_equal/less_equal_i32_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_i32_test.cairo index cb06e188b..157107ae3 100644 --- a/src/tests/operators/tensor/math/less_equal/less_equal_i32_test.cairo +++ b/src/tests/operators/tensor/math/less_equal/less_equal_i32_test.cairo @@ -31,9 +31,9 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -87,28 +87,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -149,34 +149,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); + assert(*result_a.data[9] == 1, 'result[9] = 1'); + assert(*result_a.data[10] == 1, 'result[10] = 1'); + assert(*result_a.data[11] == 1, 'result[11] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 1'); - assert(*result_b.data.at(4) == 0, 'result[4] = 1'); - assert(*result_b.data.at(5) == 0, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); - assert(*result_b.data.at(8) == 0, 'result[8] = 1'); - assert(*result_b.data.at(9) == 0, 'result[9] = 1'); - assert(*result_b.data.at(10) == 0, 'result[10] = 1'); - assert(*result_b.data.at(11) == 0, 'result[11] = 1'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 1'); + assert(*result_b.data[4] == 0, 'result[4] = 1'); + assert(*result_b.data[5] == 0, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); + assert(*result_b.data[8] == 0, 'result[8] = 1'); + assert(*result_b.data[9] == 0, 'result[9] = 1'); + assert(*result_b.data[10] == 0, 'result[10] = 1'); + assert(*result_b.data[11] == 0, 'result[11] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -228,26 +228,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 1'); - assert(*result_a.data.at(3) == 0, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 1'); + assert(*result_a.data[3] == 0, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 1'); - assert(*result_b.data.at(1) == 0, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 1, 'result[3] = 1'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 1'); - assert(*result_b.data.at(7) == 0, 'result[7] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 1'); + assert(*result_b.data[1] == 0, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 1, 'result[3] = 1'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 1'); + assert(*result_b.data[7] == 0, 'result[7] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -285,26 +285,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } diff --git a/src/tests/operators/tensor/math/less_equal/less_equal_u32_test.cairo b/src/tests/operators/tensor/math/less_equal/less_equal_u32_test.cairo index 97434920e..d82948de9 100644 --- a/src/tests/operators/tensor/math/less_equal/less_equal_u32_test.cairo +++ b/src/tests/operators/tensor/math/less_equal/less_equal_u32_test.cairo @@ -29,16 +29,16 @@ mod tensor_1D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 0, 'result[2] = 0'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 0, 'result[2] = 0'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -89,28 +89,28 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); + assert(*result_b.data[8] == 0, 'result[8] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -151,34 +151,34 @@ mod tensor_2D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); - assert(*result_a.data.at(8) == 1, 'result[8] = 1'); - assert(*result_a.data.at(9) == 1, 'result[9] = 1'); - assert(*result_a.data.at(10) == 1, 'result[10] = 1'); - assert(*result_a.data.at(11) == 1, 'result[11] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); + assert(*result_a.data[8] == 1, 'result[8] = 1'); + assert(*result_a.data[9] == 1, 'result[9] = 1'); + assert(*result_a.data[10] == 1, 'result[10] = 1'); + assert(*result_a.data[11] == 1, 'result[11] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 1, 'result[2] = 1'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); - assert(*result_b.data.at(8) == 0, 'result[8] = 0'); - assert(*result_b.data.at(9) == 0, 'result[9] = 0'); - assert(*result_b.data.at(10) == 0, 'result[10] = 0'); - assert(*result_b.data.at(11) == 0, 'result[11] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 1, 'result[2] = 1'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); + assert(*result_b.data[8] == 0, 'result[8] = 0'); + assert(*result_b.data[9] == 0, 'result[9] = 0'); + assert(*result_b.data[10] == 0, 'result[10] = 0'); + assert(*result_b.data[11] == 0, 'result[11] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -227,26 +227,26 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes.span(), arr_2.span(), extra); let result_a = tensor_a.less_equal(@tensor_b); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 0, 'result[5] = 0'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 0, 'result[5] = 0'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_b.less_equal(@tensor_a); - assert(*result_b.data.at(0) == 0, 'result[0] = 0'); - assert(*result_b.data.at(1) == 0, 'result[1] = 0'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 1, 'result[4] = 1'); - assert(*result_b.data.at(5) == 1, 'result[5] = 1'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); - assert(*result_b.data.at(7) == 0, 'result[7] = 0'); + assert(*result_b.data[0] == 0, 'result[0] = 0'); + assert(*result_b.data[1] == 0, 'result[1] = 0'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 1, 'result[4] = 1'); + assert(*result_b.data[5] == 1, 'result[5] = 1'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); + assert(*result_b.data[7] == 0, 'result[7] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } @@ -284,25 +284,25 @@ mod tensor_3D { let tensor_b = TensorTrait::::new(sizes_2.span(), arr_2.span(), extra); let result_a = tensor_b.less_equal(@tensor_a); - assert(*result_a.data.at(0) == 1, 'result[0] = 1'); - assert(*result_a.data.at(1) == 1, 'result[1] = 1'); - assert(*result_a.data.at(2) == 1, 'result[2] = 1'); - assert(*result_a.data.at(3) == 1, 'result[3] = 1'); - assert(*result_a.data.at(4) == 1, 'result[4] = 1'); - assert(*result_a.data.at(5) == 1, 'result[5] = 1'); - assert(*result_a.data.at(6) == 1, 'result[6] = 1'); - assert(*result_a.data.at(7) == 1, 'result[7] = 1'); + assert(*result_a.data[0] == 1, 'result[0] = 1'); + assert(*result_a.data[1] == 1, 'result[1] = 1'); + assert(*result_a.data[2] == 1, 'result[2] = 1'); + assert(*result_a.data[3] == 1, 'result[3] = 1'); + assert(*result_a.data[4] == 1, 'result[4] = 1'); + assert(*result_a.data[5] == 1, 'result[5] = 1'); + assert(*result_a.data[6] == 1, 'result[6] = 1'); + assert(*result_a.data[7] == 1, 'result[7] = 1'); assert(result_a.data.len() == tensor_a.data.len(), 'tensor length mismatch'); let result_b = tensor_a.less_equal(@tensor_b); - assert(*result_b.data.at(0) == 1, 'result[0] = 1'); - assert(*result_b.data.at(1) == 1, 'result[1] = 1'); - assert(*result_b.data.at(2) == 0, 'result[2] = 0'); - assert(*result_b.data.at(3) == 0, 'result[3] = 0'); - assert(*result_b.data.at(4) == 0, 'result[4] = 0'); - assert(*result_b.data.at(5) == 0, 'result[5] = 0'); - assert(*result_b.data.at(6) == 0, 'result[6] = 0'); + assert(*result_b.data[0] == 1, 'result[0] = 1'); + assert(*result_b.data[1] == 1, 'result[1] = 1'); + assert(*result_b.data[2] == 0, 'result[2] = 0'); + assert(*result_b.data[3] == 0, 'result[3] = 0'); + assert(*result_b.data[4] == 0, 'result[4] = 0'); + assert(*result_b.data[5] == 0, 'result[5] = 0'); + assert(*result_b.data[6] == 0, 'result[6] = 0'); assert(result_b.data.len() == tensor_a.data.len(), 'tensor length mismatch'); } From a255a99c2c9bafe155ae86d342f521317eee43d7 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Fri, 23 Jun 2023 13:29:18 +0300 Subject: [PATCH 051/126] Update CHANGELOG.md --- docs/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3fb8083a1..07a79e56e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] - 2023-06-23 + +### Changed +- Replace array.at with IndexView + ## [Unreleased] - 2023-06-21 ### Changed From 5c808d9b33df6ff86db035f39182ca33f9594239 Mon Sep 17 00:00:00 2001 From: Lanre Ojetokun Date: Sat, 24 Jun 2023 00:49:59 +0100 Subject: [PATCH 052/126] create replace index helper function --- src/operators/tensor/helpers.cairo | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/operators/tensor/helpers.cairo b/src/operators/tensor/helpers.cairo index d823c5cfd..48cdd06ee 100644 --- a/src/operators/tensor/helpers.cairo +++ b/src/operators/tensor/helpers.cairo @@ -309,3 +309,40 @@ fn broadcast_shape(mut shape1: Span, mut shape2: Span) -> Span` - The modified shape +fn replace_index( + mut shape: Span, + index: usize, + value: usize + ) -> Span { + let mut output = ArrayTrait::new(); + let mut i = 0; + loop { + if i == shape.len() { + break (); + }; + if i == index { + output.append(value); + } else { + output.append(*shape[i]); + }; + i += 1; + }; + return output.span(); +} From 4d93862e89bac036283a5e3241e9044cf1f42638 Mon Sep 17 00:00:00 2001 From: Lanre Ojetokun Date: Sat, 24 Jun 2023 00:53:15 +0100 Subject: [PATCH 053/126] add cumsum impl --- src/operators/tensor/core.cairo | 69 ++++++++ .../implementations/impl_tensor_fp.cairo | 6 + .../implementations/impl_tensor_i32.cairo | 5 + .../implementations/impl_tensor_u32.cairo | 5 + src/operators/tensor/math.cairo | 1 + src/operators/tensor/math/cumsum.cairo | 5 + .../tensor/math/cumsum/cumsum_fp.cairo | 3 + .../tensor/math/cumsum/cumsum_fp/core.cairo | 18 ++ .../math/cumsum/cumsum_fp/fp16x16.cairo | 26 +++ .../tensor/math/cumsum/cumsum_fp/fp8x23.cairo | 26 +++ .../tensor/math/cumsum/cumsum_i32.cairo | 24 +++ .../tensor/math/cumsum/cumsum_u32.cairo | 23 +++ .../tensor/math/cumsum/helpers.cairo | 164 ++++++++++++++++++ src/tests/operators/tensor/math.cairo | 1 + src/tests/operators/tensor/math/cumsum.cairo | 3 + 15 files changed, 379 insertions(+) create mode 100644 src/operators/tensor/math/cumsum.cairo create mode 100644 src/operators/tensor/math/cumsum/cumsum_fp.cairo create mode 100644 src/operators/tensor/math/cumsum/cumsum_fp/core.cairo create mode 100644 src/operators/tensor/math/cumsum/cumsum_fp/fp16x16.cairo create mode 100644 src/operators/tensor/math/cumsum/cumsum_fp/fp8x23.cairo create mode 100644 src/operators/tensor/math/cumsum/cumsum_i32.cairo create mode 100644 src/operators/tensor/math/cumsum/cumsum_u32.cairo create mode 100644 src/operators/tensor/math/cumsum/helpers.cairo create mode 100644 src/tests/operators/tensor/math/cumsum.cairo diff --git a/src/operators/tensor/core.cairo b/src/operators/tensor/core.cairo index 571b4e95f..434160fce 100644 --- a/src/operators/tensor/core.cairo +++ b/src/operators/tensor/core.cairo @@ -42,6 +42,7 @@ struct ExtraParams { /// less_equal - Check if each element of the first tensor is less than or equal to the corresponding element of the second tensor. /// abs - Computes the absolute value of all elements in the input tensor. /// ceil - Rounds up the value of each element in the input tensor. +/// cumsum - Returns the cumulative sum of the elements along a given axis. trait TensorTrait { /// # tensor.new /// @@ -1116,6 +1117,74 @@ trait TensorTrait { /// ``` /// fn ceil(self: @Tensor) -> Tensor; + /// # tensor.cumsum + /// + /// ```rust + /// fn cumsum(self: @Tensor, axis: usize, exclusive: Option, reverse: Option) -> Tensor; + /// ``` + /// + /// Performs cumulative sum of the input elements along the given axis. + /// + /// ## Args + /// + /// * `self`(`@Tensor`) - The input tensor. + /// * `axis`(`usize`) - The axis along which to compute the cumulative sum. + /// * `exclusive`(`Option`) - By default, it will do the sum inclusively meaning the first element is copied as is. + /// * `reverse`(`Option`) - If true, the cumulative sum is performed in the opposite direction. Defaults to false. + /// + /// ## Panics + /// + /// * Panics if axis is not in the range of the input tensor's dimensions. + /// + /// ## Returns + /// + /// A new `Tensor` instance containing the cumulative sum of the input tensor's elements along the given axis. + /// + /// ## Examples + /// + /// Case 1: cumsum with default parameters + /// + /// ```rust + /// fn cumsum_example() -> Tensor { + /// // We instantiate a 3D Tensor here. + /// // [[[0,1],[2,3]],[[4,5],[6,7]]] + /// let tensor = u32_tensor_2x2x2_helper(); + /// + /// // We can call `cumsum` function as follows. + /// return tensor.cumsum(2,Option::None(()),Option::None(())); + /// } + /// >>> [[[0,1],[2,5]],[[4,9],[6,13]]] + /// ``` + /// + /// Case 2: cumsum with exclusive = true + /// + /// ```rust + /// fn cumsum_example() -> Tensor { + /// // We instantiate a 3D Tensor here. + /// // [[[0,1],[2,3]],[[4,5],[6,7]]] + /// let tensor = u32_tensor_2x2x2_helper(); + /// + /// // We can call `cumsum` function as follows. + /// return tensor.cumsum(2,Option::Some(true),Option::None(())); + /// } + /// >>> [[[0,0],[0,2]],[[0,4],[0,6]]] + /// ``` + /// + /// Case 3: cumsum with exclusive = true and reverse = true + /// + /// ```rust + /// fn cumsum_example() -> Tensor { + /// // We instantiate a 3D Tensor here. + /// // [[[0,1],[2,3]],[[4,5],[6,7]]] + /// let tensor = u32_tensor_2x2x2_helper(); + /// + /// // We can call `cumsum` function as follows. + /// return tensor.cumsum(2,Option::Some(true),Option::Some(true)); + /// } + /// >>> [[[1,0],[3,0]],[[5,0],[7,0]]] + /// ``` + /// + fn cumsum(self: @Tensor, axis: usize, exclusive: Option, reverse: Option) -> Tensor; } /// Cf: TensorTrait::new docstring diff --git a/src/operators/tensor/implementations/impl_tensor_fp.cairo b/src/operators/tensor/implementations/impl_tensor_fp.cairo index 4920501a0..8e3666302 100644 --- a/src/operators/tensor/implementations/impl_tensor_fp.cairo +++ b/src/operators/tensor/implementations/impl_tensor_fp.cairo @@ -27,6 +27,8 @@ use orion::operators::tensor::math::ln::ln_fp::core::ln; use orion::operators::tensor::math::arithmetic::arithmetic_fp::core::{add, sub, mul, div}; use orion::operators::tensor::math::greater::greater_fp::core::greater; use orion::operators::tensor::math::greater_equal::greater_equal_fp::core::greater_equal; +use orion::operators::tensor::math::cumsum::cumsum_fp::core::cumsum; + use orion::utils::check_gas; impl Tensor_fp of TensorTrait { @@ -119,6 +121,10 @@ impl Tensor_fp of TensorTrait { fn ceil(self: @Tensor) -> Tensor { ceil(self).unwrap() } + + fn cumsum(self: @Tensor, axis: usize, exclusive:Option, reverse:Option) -> Tensor { + cumsum(self, axis, exclusive, reverse).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_i32.cairo b/src/operators/tensor/implementations/impl_tensor_i32.cairo index 4b6ccfd21..586b81060 100644 --- a/src/operators/tensor/implementations/impl_tensor_i32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_i32.cairo @@ -28,6 +28,7 @@ use orion::operators::tensor::linalg::transpose::transpose_i32::transpose; use orion::operators::tensor::math::exp::exp_i32::core::exp_i32; use orion::operators::tensor::math::ln::ln_i32::core::ln_i32; use orion::operators::tensor::math::arithmetic::arithmetic_i32::{add, sub, mul, div}; +use orion::operators::tensor::math::cumsum::cumsum_i32::cumsum; use orion::utils::check_gas; impl Tensor_i32 of TensorTrait { @@ -118,6 +119,10 @@ impl Tensor_i32 of TensorTrait { fn ceil(self: @Tensor) -> Tensor { ceil(self) } + + fn cumsum(self: @Tensor, axis: usize, exclusive:Option, reverse:Option) -> Tensor { + cumsum(self, axis, exclusive, reverse) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_u32.cairo b/src/operators/tensor/implementations/impl_tensor_u32.cairo index 9c0ca8838..4cf84524a 100644 --- a/src/operators/tensor/implementations/impl_tensor_u32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_u32.cairo @@ -27,6 +27,7 @@ use orion::operators::tensor::linalg::transpose::transpose_u32::transpose; use orion::operators::tensor::math::exp::exp_u32::core::exp_u32; use orion::operators::tensor::math::ln::ln_u32::core::ln_u32; use orion::operators::tensor::math::arithmetic::arithmetic_u32::{add, sub, mul, div}; +use orion::operators::tensor::math::cumsum::cumsum_u32::cumsum; use orion::utils::check_gas; impl Tensor_u32 of TensorTrait { @@ -118,6 +119,10 @@ impl Tensor_u32 of TensorTrait { fn ceil(self: @Tensor) -> Tensor { ceil(self) } + + fn cumsum(self: @Tensor, axis: usize, exclusive:Option, reverse:Option) -> Tensor { + cumsum(self, axis, exclusive, reverse) + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/math.cairo b/src/operators/tensor/math.cairo index b73d95f4b..f21ba3d67 100644 --- a/src/operators/tensor/math.cairo +++ b/src/operators/tensor/math.cairo @@ -13,3 +13,4 @@ mod less; mod less_equal; mod abs; mod ceil; +mod cumsum; diff --git a/src/operators/tensor/math/cumsum.cairo b/src/operators/tensor/math/cumsum.cairo new file mode 100644 index 000000000..409b30b80 --- /dev/null +++ b/src/operators/tensor/math/cumsum.cairo @@ -0,0 +1,5 @@ +mod cumsum_i32; +mod cumsum_u32; +mod cumsum_fp; +mod helpers; + diff --git a/src/operators/tensor/math/cumsum/cumsum_fp.cairo b/src/operators/tensor/math/cumsum/cumsum_fp.cairo new file mode 100644 index 000000000..50d44d68c --- /dev/null +++ b/src/operators/tensor/math/cumsum/cumsum_fp.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; diff --git a/src/operators/tensor/math/cumsum/cumsum_fp/core.cairo b/src/operators/tensor/math/cumsum/cumsum_fp/core.cairo new file mode 100644 index 000000000..b9ff0a2ba --- /dev/null +++ b/src/operators/tensor/math/cumsum/cumsum_fp/core.cairo @@ -0,0 +1,18 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::Tensor; +use orion::operators::tensor::math::cumsum::cumsum_fp::fp8x23; +use orion::operators::tensor::math::cumsum::cumsum_fp::fp16x16; + +/// Cf: TensorTrait::cumsum docstring +fn cumsum(self: @Tensor, axis: usize, exclusive: Option, reverse: Option ) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::cumsum(self, axis, exclusive, reverse)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::cumsum(self, axis, exclusive, reverse)), + }, + Option::None(_) => Option::Some(fp16x16::cumsum(self, axis, exclusive, reverse)), + }, + Option::None(_) => Option::Some(fp16x16::cumsum(self, axis, exclusive, reverse)), + } +} diff --git a/src/operators/tensor/math/cumsum/cumsum_fp/fp16x16.cairo b/src/operators/tensor/math/cumsum/cumsum_fp/fp16x16.cairo new file mode 100644 index 000000000..60c3f3282 --- /dev/null +++ b/src/operators/tensor/math/cumsum/cumsum_fp/fp16x16.cairo @@ -0,0 +1,26 @@ + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl, FP16x16Add, FP16x16Sub, FP16x16AddEq}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::operators::tensor::core::Tensor; +use orion::operators::tensor::math::cumsum::helpers::{cumsum_forward, cumsum_reverse}; + + +/// Cf: TensorTrait::cumsum docstring +fn cumsum( + self: @Tensor, + axis: usize, + exclusive: Option, + reverse: Option + ) -> Tensor { + + let reverse = match reverse { + Option::Some(val) => val, + Option::None(_) => false + }; + + if reverse { + cumsum_reverse(self, axis, exclusive, FixedTrait::new(0,false)) + } else { + cumsum_forward(self, axis, exclusive, FixedTrait::new(0,false)) + } +} \ No newline at end of file diff --git a/src/operators/tensor/math/cumsum/cumsum_fp/fp8x23.cairo b/src/operators/tensor/math/cumsum/cumsum_fp/fp8x23.cairo new file mode 100644 index 000000000..b96837113 --- /dev/null +++ b/src/operators/tensor/math/cumsum/cumsum_fp/fp8x23.cairo @@ -0,0 +1,26 @@ + use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl, FP8x23Add, FP8x23Sub, FP8x23AddEq}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::operators::tensor::core::Tensor; +use orion::operators::tensor::math::cumsum::helpers::{cumsum_forward, cumsum_reverse}; + + +/// Cf: TensorTrait::cumsum docstring +fn cumsum( + self: @Tensor, + axis: usize, + exclusive: Option, + reverse: Option + ) -> Tensor { + + let reverse = match reverse { + Option::Some(val) => val, + Option::None(_) => false + }; + + if reverse { + cumsum_reverse(self, axis, exclusive, FixedTrait::new(0,false)) + } else { + cumsum_forward(self, axis, exclusive, FixedTrait::new(0,false)) + } +} \ No newline at end of file diff --git a/src/operators/tensor/math/cumsum/cumsum_i32.cairo b/src/operators/tensor/math/cumsum/cumsum_i32.cairo new file mode 100644 index 000000000..c2dbc7afe --- /dev/null +++ b/src/operators/tensor/math/cumsum/cumsum_i32.cairo @@ -0,0 +1,24 @@ +use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; +use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; +use orion::operators::tensor::core::Tensor; +use orion::operators::tensor::math::cumsum::helpers::{cumsum_forward, cumsum_reverse}; + +/// Cf: TensorTrait::cumsum docstring +fn cumsum( + self: @Tensor, + axis: usize, + exclusive: Option, + reverse: Option + ) -> Tensor { + + let reverse = match reverse { + Option::Some(val) => val, + Option::None(_) => false + }; + + if reverse { + cumsum_reverse(self, axis, exclusive, IntegerTrait::new(0,false)) + } else { + cumsum_forward(self, axis, exclusive, IntegerTrait::new(0,false)) + } +} diff --git a/src/operators/tensor/math/cumsum/cumsum_u32.cairo b/src/operators/tensor/math/cumsum/cumsum_u32.cairo new file mode 100644 index 000000000..b6fc5ddc0 --- /dev/null +++ b/src/operators/tensor/math/cumsum/cumsum_u32.cairo @@ -0,0 +1,23 @@ +use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; +use orion::operators::tensor::core::Tensor; +use orion::operators::tensor::math::cumsum::helpers::{cumsum_forward, cumsum_reverse}; + +/// Cf: TensorTrait::cumsum docstring +fn cumsum( + self: @Tensor, + axis: usize, + exclusive: Option, + reverse: Option, + ) -> Tensor { + + let reverse = match reverse { + Option::Some(val) => val, + Option::None(_) => false + }; + + if reverse { + cumsum_reverse(self, axis, exclusive, 0) + } else { + cumsum_forward(self, axis, exclusive, 0) + } +} diff --git a/src/operators/tensor/math/cumsum/helpers.cairo b/src/operators/tensor/math/cumsum/helpers.cairo new file mode 100644 index 000000000..ab7018d8f --- /dev/null +++ b/src/operators/tensor/math/cumsum/helpers.cairo @@ -0,0 +1,164 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use debug::PrintTrait; + +use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; +use orion::operators::tensor::implementations::{impl_tensor_i32, impl_tensor_u32}; +use orion::operators::tensor::helpers::replace_index; +use orion::operators::tensor::core::{Tensor, TensorTrait, ravel_index, unravel_index}; +use orion::utils::check_gas; + +/// Cf: TensorTrait::cumsum docstring +fn cumsum_forward, + impl TAdd: Add, + impl TCopy: Copy, + impl TDrop: Drop, +>( + self: @Tensor, + axis: usize, + exclusive: Option, + zero: T, + ) -> Tensor { + + let exclusive = match exclusive { + Option::Some(val) => val, + Option::None(_) => false, + }; + + assert(axis < (*self.shape).len(), 'axis out of dimensions'); + + let data = *self.data; + + let mut output_data = ArrayTrait::new(); + + let mut index: usize = 0; + + loop { + check_gas(); + + if index == data.len() { + break (); + }; + + let current_indices = unravel_index(index, *self.shape); + let axis_value = *current_indices[axis]; + if axis_value == 0 { + if exclusive { + output_data.append(zero); + } else { + output_data.append(*(data)[index]); + } + } else { + + let previous_axis_element_indices = replace_index(current_indices, axis, axis_value - 1); + let previous_axis_element_index = ravel_index(*self.shape, previous_axis_element_indices); + + if exclusive { + output_data.append( + *output_data[previous_axis_element_index] + + *(data)[previous_axis_element_index] + ); + } else { + output_data.append( + *output_data[previous_axis_element_index] + + *(data)[index] + ); + }; + } + + index += 1; + + }; + + return TensorTrait::::new(*self.shape, output_data.span(), *self.extra); +} + + + + +/// Cf: TensorTrait::cumsum docstring +fn cumsum_reverse, + impl TAddEq: AddEq, + impl TSub: Sub, + impl TCopy: Copy, + impl TDrop: Drop, +>( + self: @Tensor, + axis: usize, + exclusive: Option, + zero: T, + ) -> Tensor { + + let exclusive = match exclusive { + Option::Some(val) => val, + Option::None(_) => false, + }; + + + assert(axis < (*self.shape).len(), 'axis out of dimensions'); + let data = *self.data; + let mut output_data = ArrayTrait::new(); + let mut index: usize = 0; + loop { + check_gas(); + + if index == data.len() { + break (); + }; + + let current_indices = unravel_index(index, *self.shape); + let mut axis_value = *current_indices[axis]; + + if axis_value == 0 { + // If the axis value is 0, we need to sum all the elements + // in the axis. + + let mut sum = *(data)[index]; + if exclusive { + sum = zero; + } + + let end_index = *(*self.shape)[axis] - 1; + + loop { + + axis_value += 1; + if axis_value > end_index{ + break (); + } + + let next_axis_element_indices = replace_index(current_indices, axis, axis_value); + let next_axis_element_index = ravel_index(*self.shape, next_axis_element_indices); + sum += *data[next_axis_element_index]; + + }; + output_data.append(sum); + + } else { + // If the axis value is not 0, we only need to do a subtraction + let previous_axis_element_indices = replace_index(current_indices, axis, axis_value - 1); + let previous_axis_element_index = ravel_index(*self.shape, previous_axis_element_indices); + let mut z = *(data)[previous_axis_element_index]; + + if exclusive { + output_data.append( + *output_data[previous_axis_element_index] - + *(data)[index] + ); + } else { + output_data.append( + *output_data[previous_axis_element_index] - + *(data)[previous_axis_element_index] + ); + } + } + + index += 1; + + }; + + return TensorTrait::::new(*self.shape, output_data.span(), *self.extra); + } diff --git a/src/tests/operators/tensor/math.cairo b/src/tests/operators/tensor/math.cairo index 826039c61..994687538 100644 --- a/src/tests/operators/tensor/math.cairo +++ b/src/tests/operators/tensor/math.cairo @@ -13,3 +13,4 @@ mod abs; mod ceil; mod ln; mod arithmetic; +mod cumsum; diff --git a/src/tests/operators/tensor/math/cumsum.cairo b/src/tests/operators/tensor/math/cumsum.cairo new file mode 100644 index 000000000..0e348e579 --- /dev/null +++ b/src/tests/operators/tensor/math/cumsum.cairo @@ -0,0 +1,3 @@ +mod cumsum_u32_test; +mod cumsum_i32_test; +mod cumsum_fp_test; \ No newline at end of file From 114cbed117a0c9dfe887b8046bb3e1b4b967ba89 Mon Sep 17 00:00:00 2001 From: Lanre Ojetokun Date: Sat, 24 Jun 2023 00:53:37 +0100 Subject: [PATCH 054/126] add cumsum tests --- .../tensor/math/cumsum/cumsum_fp_test.cairo | 2 + .../cumsum_fp_test/cumsum_fp16x16_test.cairo | 398 ++++++++++++++++++ .../cumsum_fp_test/cumsum_fp8x23_test.cairo | 398 ++++++++++++++++++ .../tensor/math/cumsum/cumsum_i32_test.cairo | 389 +++++++++++++++++ .../tensor/math/cumsum/cumsum_u32_test.cairo | 389 +++++++++++++++++ 5 files changed, 1576 insertions(+) create mode 100644 src/tests/operators/tensor/math/cumsum/cumsum_fp_test.cairo create mode 100644 src/tests/operators/tensor/math/cumsum/cumsum_fp_test/cumsum_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/math/cumsum/cumsum_fp_test/cumsum_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/math/cumsum/cumsum_i32_test.cairo create mode 100644 src/tests/operators/tensor/math/cumsum/cumsum_u32_test.cairo diff --git a/src/tests/operators/tensor/math/cumsum/cumsum_fp_test.cairo b/src/tests/operators/tensor/math/cumsum/cumsum_fp_test.cairo new file mode 100644 index 000000000..b3871718b --- /dev/null +++ b/src/tests/operators/tensor/math/cumsum/cumsum_fp_test.cairo @@ -0,0 +1,2 @@ +mod cumsum_fp8x23_test; +mod cumsum_fp16x16_test; diff --git a/src/tests/operators/tensor/math/cumsum/cumsum_fp_test/cumsum_fp16x16_test.cairo b/src/tests/operators/tensor/math/cumsum/cumsum_fp_test/cumsum_fp16x16_test.cairo new file mode 100644 index 000000000..5f01607db --- /dev/null +++ b/src/tests/operators/tensor/math/cumsum/cumsum_fp_test/cumsum_fp16x16_test.cairo @@ -0,0 +1,398 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl,FP16x16Into,FP16x16PartialEq}; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::operators::tensor::core::TensorTrait; + + + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(3,false), 'result[2] = 3'); + } + + #[test] + #[available_gas(20000000)] + fn changed_parameters() { + + // exclusive = false and reverse = false + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(3,false), 'result[2] = 3'); + + // exclusive = false and reverse = true + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(3,false), 'result[0] = 3'); + assert((*result.data[1]) == FixedTrait::new_unscaled(3,false), 'result[1] = 3'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + + // exclusive = true and reverse = false + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(1,false), 'result[2] = 1'); + + // exclusive = true and reverse = true + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(3,false), 'result[0] = 3'); + assert((*result.data[1]) == FixedTrait::new_unscaled(2,false), 'result[1] = 2'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + + } + +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl,FP16x16Into,FP16x16PartialEq}; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::operators::tensor::core::TensorTrait; + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = fp_tensor_2x2_helper(); + // axis = 0 + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(4,false), 'result[3] = 4'); + + // axis = 1 + let result = tensor.cumsum(1, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(5,false), 'result[3] = 5'); + } + + + #[test] + #[available_gas(20000000)] + fn changed_parameters() { + + // axis = 0 exclusive = false and reverse = false + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(4,false), 'result[3] = 4'); + + // axis = 0 exclusive = false and reverse = true + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(2,false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4,false), 'result[1] = 4'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + + // axis = 0 exclusive = true and reverse = false + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(1,false), 'result[3] = 1'); + + // axis = 0 exclusive = true and reverse = true + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(2,false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(3,false), 'result[1] = 3'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + + + + + + // axis = 1 exclusive = false and reverse = false + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(5,false), 'result[3] = 5'); + + // axis = 1 exclusive = false and reverse = true + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(1,false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(5,false), 'result[2] = 5'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + + // axis = 1 exclusive = true and reverse = false + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(2,false), 'result[3] = 2'); + + // axis = 1 exclusive = true and reverse = true + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(1,false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(3,false), 'result[2] = 3'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + + } + + + +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_16x16::{FP16x16Impl,FP16x16Into,FP16x16PartialEq}; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::operators::tensor::core::TensorTrait; + + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = fp_tensor_2x2x2_helper(); + + // axis = 0 + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(6,false), 'result[5] = 6'); + assert((*result.data[6]) == FixedTrait::new_unscaled(8,false), 'result[6] = 8'); + assert((*result.data[7]) == FixedTrait::new_unscaled(10,false),'result[7] = 10'); + + + // axis = 1 + let result = tensor.cumsum(1, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(4,false), 'result[3] = 4'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(5,false), 'result[5] = 5'); + assert((*result.data[6]) == FixedTrait::new_unscaled(10,false), 'result[6] = 10'); + assert((*result.data[7]) == FixedTrait::new_unscaled(12,false), 'result[7] = 12'); + + + // axis = 2 + let result = tensor.cumsum(2, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(5,false), 'result[3] = 5'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(9,false), 'result[5] = 9'); + assert((*result.data[6]) == FixedTrait::new_unscaled(6,false), 'result[6] = 6'); + assert((*result.data[7]) == FixedTrait::new_unscaled(13,false), 'result[7] = 13'); + } + + + + #[test] + #[available_gas(40000000)] + fn changed_parameters() { + + // axis = 0 exclusive = false and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(6,false), 'result[5] = 6'); + assert((*result.data[6]) == FixedTrait::new_unscaled(8,false), 'result[6] = 8'); + assert((*result.data[7]) == FixedTrait::new_unscaled(10,false),'result[7] = 10'); + + + // axis = 0 exclusive = false and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(4,false), 'result[0] = 4'); + assert((*result.data[1]) == FixedTrait::new_unscaled(6,false), 'result[1] = 6'); + assert((*result.data[2]) == FixedTrait::new_unscaled(8,false), 'result[2] = 8'); + assert((*result.data[3]) == FixedTrait::new_unscaled(10,false), 'result[3] = 10'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(5,false), 'result[5] = 5'); + assert((*result.data[6]) == FixedTrait::new_unscaled(6,false), 'result[6] = 6'); + assert((*result.data[7]) == FixedTrait::new_unscaled(7,false), 'result[7] = 7'); + + // axis = 0 exclusive = true and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + assert((*result.data[4]) == FixedTrait::new_unscaled(0,false), 'result[4] = 0'); + assert((*result.data[5]) == FixedTrait::new_unscaled(1,false), 'result[5] = 1'); + assert((*result.data[6]) == FixedTrait::new_unscaled(2,false), 'result[6] = 2'); + assert((*result.data[7]) == FixedTrait::new_unscaled(3,false), 'result[7] = 3'); + + // axis = 0 exclusive = true and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(4,false), 'result[0] = 4'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5,false), 'result[1] = 5'); + assert((*result.data[2]) == FixedTrait::new_unscaled(6,false), 'result[2] = 6'); + assert((*result.data[3]) == FixedTrait::new_unscaled(7,false), 'result[3] = 7'); + assert((*result.data[4]) == FixedTrait::new_unscaled(0,false), 'result[4] = 0'); + assert((*result.data[5]) == FixedTrait::new_unscaled(0,false), 'result[5] = 0'); + assert((*result.data[6]) == FixedTrait::new_unscaled(0,false), 'result[6] = 0'); + assert((*result.data[7]) == FixedTrait::new_unscaled(0,false), 'result[7] = 0'); + + + + + + + // axis = 1 exclusive = false and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(4,false), 'result[3] = 4'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(5,false), 'result[5] = 5'); + assert((*result.data[6]) == FixedTrait::new_unscaled(10,false), 'result[6] = 10'); + assert((*result.data[7]) == FixedTrait::new_unscaled(12,false), 'result[7] = 12'); + + + // axis = 1 exclusive = false and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(2,false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4,false), 'result[1] = 4'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + assert((*result.data[4]) == FixedTrait::new_unscaled(10,false), 'result[4] = 10'); + assert((*result.data[5]) == FixedTrait::new_unscaled(12,false), 'result[5] = 12'); + assert((*result.data[6]) == FixedTrait::new_unscaled(6,false), 'result[6] = 6'); + assert((*result.data[7]) == FixedTrait::new_unscaled(7,false), 'result[7] = 7'); + + + // axis = 1 exclusive = true and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(1,false), 'result[3] = 1'); + assert((*result.data[4]) == FixedTrait::new_unscaled(0,false), 'result[4] = 0'); + assert((*result.data[5]) == FixedTrait::new_unscaled(0,false), 'result[5] = 0'); + assert((*result.data[6]) == FixedTrait::new_unscaled(4,false), 'result[6] = 4'); + assert((*result.data[7]) == FixedTrait::new_unscaled(5,false), 'result[7] = 5'); + + // axis = 1 exclusive = true and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(2,false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(3,false), 'result[1] = 3'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + assert((*result.data[4]) == FixedTrait::new_unscaled(6,false), 'result[4] = 6'); + assert((*result.data[5]) == FixedTrait::new_unscaled(7,false), 'result[5] = 7'); + assert((*result.data[6]) == FixedTrait::new_unscaled(0,false), 'result[6] = 0'); + assert((*result.data[7]) == FixedTrait::new_unscaled(0,false), 'result[7] = 0'); + + + + + + + + + // axis = 2 exclusive = false and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(5,false), 'result[3] = 5'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(9,false), 'result[5] = 9'); + assert((*result.data[6]) == FixedTrait::new_unscaled(6,false), 'result[6] = 6'); + assert((*result.data[7]) == FixedTrait::new_unscaled(13,false), 'result[7] = 13'); + + // axis = 2 exclusive = false and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(1,false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(5,false), 'result[2] = 5'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + assert((*result.data[4]) == FixedTrait::new_unscaled(9,false), 'result[4] = 9'); + assert((*result.data[5]) == FixedTrait::new_unscaled(5,false), 'result[5] = 5'); + assert((*result.data[6]) == FixedTrait::new_unscaled(13,false), 'result[6] = 13'); + assert((*result.data[7]) == FixedTrait::new_unscaled(7,false), 'result[7] = 7'); + + // axis = 2 exclusive = true and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(2,false), 'result[3] = 2'); + assert((*result.data[4]) == FixedTrait::new_unscaled(0,false), 'result[4] = 0'); + assert((*result.data[5]) == FixedTrait::new_unscaled(4,false), 'result[5] = 4'); + assert((*result.data[6]) == FixedTrait::new_unscaled(0,false), 'result[6] = 0'); + assert((*result.data[7]) == FixedTrait::new_unscaled(6,false), 'result[7] = 6'); + + // axis = 2 exclusive = true and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(1,false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(3,false), 'result[2] = 3'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + assert((*result.data[4]) == FixedTrait::new_unscaled(5,false), 'result[4] = 5'); + assert((*result.data[5]) == FixedTrait::new_unscaled(0,false), 'result[5] = 0'); + assert((*result.data[6]) == FixedTrait::new_unscaled(7,false), 'result[6] = 7'); + assert((*result.data[7]) == FixedTrait::new_unscaled(0,false), 'result[7] = 0'); + + } + +} diff --git a/src/tests/operators/tensor/math/cumsum/cumsum_fp_test/cumsum_fp8x23_test.cairo b/src/tests/operators/tensor/math/cumsum/cumsum_fp_test/cumsum_fp8x23_test.cairo new file mode 100644 index 000000000..9b4c3c187 --- /dev/null +++ b/src/tests/operators/tensor/math/cumsum/cumsum_fp_test/cumsum_fp8x23_test.cairo @@ -0,0 +1,398 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl,FP8x23Into,FP8x23PartialEq}; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::operators::tensor::core::TensorTrait; + + + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(3,false), 'result[2] = 3'); + } + + #[test] + #[available_gas(20000000)] + fn changed_parameters() { + + // exclusive = false and reverse = false + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(3,false), 'result[2] = 3'); + + // exclusive = false and reverse = true + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(3,false), 'result[0] = 3'); + assert((*result.data[1]) == FixedTrait::new_unscaled(3,false), 'result[1] = 3'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + + // exclusive = true and reverse = false + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(1,false), 'result[2] = 1'); + + // exclusive = true and reverse = true + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(3,false), 'result[0] = 3'); + assert((*result.data[1]) == FixedTrait::new_unscaled(2,false), 'result[1] = 2'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + + } + +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl,FP8x23Into,FP8x23PartialEq}; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::operators::tensor::core::TensorTrait; + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = fp_tensor_2x2_helper(); + // axis = 0 + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(4,false), 'result[3] = 4'); + + // axis = 1 + let result = tensor.cumsum(1, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(5,false), 'result[3] = 5'); + } + + + #[test] + #[available_gas(20000000)] + fn changed_parameters() { + + // axis = 0 exclusive = false and reverse = false + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(4,false), 'result[3] = 4'); + + // axis = 0 exclusive = false and reverse = true + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(2,false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4,false), 'result[1] = 4'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + + // axis = 0 exclusive = true and reverse = false + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(1,false), 'result[3] = 1'); + + // axis = 0 exclusive = true and reverse = true + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(2,false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(3,false), 'result[1] = 3'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + + + + + + // axis = 1 exclusive = false and reverse = false + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(5,false), 'result[3] = 5'); + + // axis = 1 exclusive = false and reverse = true + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(1,false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(5,false), 'result[2] = 5'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + + // axis = 1 exclusive = true and reverse = false + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(2,false), 'result[3] = 2'); + + // axis = 1 exclusive = true and reverse = true + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(1,false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(3,false), 'result[2] = 3'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + + } + + + +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + use orion::numbers::fixed_point::core::{FixedTrait, FixedType, FixedImpl}; + use orion::numbers::fixed_point::implementations::impl_8x23::{FP8x23Impl,FP8x23Into,FP8x23PartialEq}; + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::operators::tensor::core::TensorTrait; + + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = fp_tensor_2x2x2_helper(); + + // axis = 0 + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(6,false), 'result[5] = 6'); + assert((*result.data[6]) == FixedTrait::new_unscaled(8,false), 'result[6] = 8'); + assert((*result.data[7]) == FixedTrait::new_unscaled(10,false),'result[7] = 10'); + + + // axis = 1 + let result = tensor.cumsum(1, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(4,false), 'result[3] = 4'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(5,false), 'result[5] = 5'); + assert((*result.data[6]) == FixedTrait::new_unscaled(10,false), 'result[6] = 10'); + assert((*result.data[7]) == FixedTrait::new_unscaled(12,false), 'result[7] = 12'); + + + // axis = 2 + let result = tensor.cumsum(2, Option::None(()), Option::None(())); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(5,false), 'result[3] = 5'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(9,false), 'result[5] = 9'); + assert((*result.data[6]) == FixedTrait::new_unscaled(6,false), 'result[6] = 6'); + assert((*result.data[7]) == FixedTrait::new_unscaled(13,false), 'result[7] = 13'); + } + + + + #[test] + #[available_gas(40000000)] + fn changed_parameters() { + + // axis = 0 exclusive = false and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(6,false), 'result[5] = 6'); + assert((*result.data[6]) == FixedTrait::new_unscaled(8,false), 'result[6] = 8'); + assert((*result.data[7]) == FixedTrait::new_unscaled(10,false),'result[7] = 10'); + + + // axis = 0 exclusive = false and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(4,false), 'result[0] = 4'); + assert((*result.data[1]) == FixedTrait::new_unscaled(6,false), 'result[1] = 6'); + assert((*result.data[2]) == FixedTrait::new_unscaled(8,false), 'result[2] = 8'); + assert((*result.data[3]) == FixedTrait::new_unscaled(10,false), 'result[3] = 10'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(5,false), 'result[5] = 5'); + assert((*result.data[6]) == FixedTrait::new_unscaled(6,false), 'result[6] = 6'); + assert((*result.data[7]) == FixedTrait::new_unscaled(7,false), 'result[7] = 7'); + + // axis = 0 exclusive = true and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + assert((*result.data[4]) == FixedTrait::new_unscaled(0,false), 'result[4] = 0'); + assert((*result.data[5]) == FixedTrait::new_unscaled(1,false), 'result[5] = 1'); + assert((*result.data[6]) == FixedTrait::new_unscaled(2,false), 'result[6] = 2'); + assert((*result.data[7]) == FixedTrait::new_unscaled(3,false), 'result[7] = 3'); + + // axis = 0 exclusive = true and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(4,false), 'result[0] = 4'); + assert((*result.data[1]) == FixedTrait::new_unscaled(5,false), 'result[1] = 5'); + assert((*result.data[2]) == FixedTrait::new_unscaled(6,false), 'result[2] = 6'); + assert((*result.data[3]) == FixedTrait::new_unscaled(7,false), 'result[3] = 7'); + assert((*result.data[4]) == FixedTrait::new_unscaled(0,false), 'result[4] = 0'); + assert((*result.data[5]) == FixedTrait::new_unscaled(0,false), 'result[5] = 0'); + assert((*result.data[6]) == FixedTrait::new_unscaled(0,false), 'result[6] = 0'); + assert((*result.data[7]) == FixedTrait::new_unscaled(0,false), 'result[7] = 0'); + + + + + + + // axis = 1 exclusive = false and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(4,false), 'result[3] = 4'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(5,false), 'result[5] = 5'); + assert((*result.data[6]) == FixedTrait::new_unscaled(10,false), 'result[6] = 10'); + assert((*result.data[7]) == FixedTrait::new_unscaled(12,false), 'result[7] = 12'); + + + // axis = 1 exclusive = false and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(2,false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(4,false), 'result[1] = 4'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + assert((*result.data[4]) == FixedTrait::new_unscaled(10,false), 'result[4] = 10'); + assert((*result.data[5]) == FixedTrait::new_unscaled(12,false), 'result[5] = 12'); + assert((*result.data[6]) == FixedTrait::new_unscaled(6,false), 'result[6] = 6'); + assert((*result.data[7]) == FixedTrait::new_unscaled(7,false), 'result[7] = 7'); + + + // axis = 1 exclusive = true and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(1,false), 'result[3] = 1'); + assert((*result.data[4]) == FixedTrait::new_unscaled(0,false), 'result[4] = 0'); + assert((*result.data[5]) == FixedTrait::new_unscaled(0,false), 'result[5] = 0'); + assert((*result.data[6]) == FixedTrait::new_unscaled(4,false), 'result[6] = 4'); + assert((*result.data[7]) == FixedTrait::new_unscaled(5,false), 'result[7] = 5'); + + // axis = 1 exclusive = true and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(2,false), 'result[0] = 2'); + assert((*result.data[1]) == FixedTrait::new_unscaled(3,false), 'result[1] = 3'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + assert((*result.data[4]) == FixedTrait::new_unscaled(6,false), 'result[4] = 6'); + assert((*result.data[5]) == FixedTrait::new_unscaled(7,false), 'result[5] = 7'); + assert((*result.data[6]) == FixedTrait::new_unscaled(0,false), 'result[6] = 0'); + assert((*result.data[7]) == FixedTrait::new_unscaled(0,false), 'result[7] = 0'); + + + + + + + + + // axis = 2 exclusive = false and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(false), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(2,false), 'result[2] = 2'); + assert((*result.data[3]) == FixedTrait::new_unscaled(5,false), 'result[3] = 5'); + assert((*result.data[4]) == FixedTrait::new_unscaled(4,false), 'result[4] = 4'); + assert((*result.data[5]) == FixedTrait::new_unscaled(9,false), 'result[5] = 9'); + assert((*result.data[6]) == FixedTrait::new_unscaled(6,false), 'result[6] = 6'); + assert((*result.data[7]) == FixedTrait::new_unscaled(13,false), 'result[7] = 13'); + + // axis = 2 exclusive = false and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(false), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(1,false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(1,false), 'result[1] = 1'); + assert((*result.data[2]) == FixedTrait::new_unscaled(5,false), 'result[2] = 5'); + assert((*result.data[3]) == FixedTrait::new_unscaled(3,false), 'result[3] = 3'); + assert((*result.data[4]) == FixedTrait::new_unscaled(9,false), 'result[4] = 9'); + assert((*result.data[5]) == FixedTrait::new_unscaled(5,false), 'result[5] = 5'); + assert((*result.data[6]) == FixedTrait::new_unscaled(13,false), 'result[6] = 13'); + assert((*result.data[7]) == FixedTrait::new_unscaled(7,false), 'result[7] = 7'); + + // axis = 2 exclusive = true and reverse = false + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(true), Option::Some(false)); + assert((*result.data[0]) == FixedTrait::new_unscaled(0,false), 'result[0] = 0'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(0,false), 'result[2] = 0'); + assert((*result.data[3]) == FixedTrait::new_unscaled(2,false), 'result[3] = 2'); + assert((*result.data[4]) == FixedTrait::new_unscaled(0,false), 'result[4] = 0'); + assert((*result.data[5]) == FixedTrait::new_unscaled(4,false), 'result[5] = 4'); + assert((*result.data[6]) == FixedTrait::new_unscaled(0,false), 'result[6] = 0'); + assert((*result.data[7]) == FixedTrait::new_unscaled(6,false), 'result[7] = 6'); + + // axis = 2 exclusive = true and reverse = true + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(true), Option::Some(true)); + assert((*result.data[0]) == FixedTrait::new_unscaled(1,false), 'result[0] = 1'); + assert((*result.data[1]) == FixedTrait::new_unscaled(0,false), 'result[1] = 0'); + assert((*result.data[2]) == FixedTrait::new_unscaled(3,false), 'result[2] = 3'); + assert((*result.data[3]) == FixedTrait::new_unscaled(0,false), 'result[3] = 0'); + assert((*result.data[4]) == FixedTrait::new_unscaled(5,false), 'result[4] = 5'); + assert((*result.data[5]) == FixedTrait::new_unscaled(0,false), 'result[5] = 0'); + assert((*result.data[6]) == FixedTrait::new_unscaled(7,false), 'result[6] = 7'); + assert((*result.data[7]) == FixedTrait::new_unscaled(0,false), 'result[7] = 0'); + + } + +} diff --git a/src/tests/operators/tensor/math/cumsum/cumsum_i32_test.cairo b/src/tests/operators/tensor/math/cumsum/cumsum_i32_test.cairo new file mode 100644 index 000000000..2c7cdcc5d --- /dev/null +++ b/src/tests/operators/tensor/math/cumsum/cumsum_i32_test.cairo @@ -0,0 +1,389 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = i32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 3, 'result[2] = 3'); + } + + #[test] + #[available_gas(20000000)] + fn changed_parameters() { + + // exclusive = false and reverse = false + let tensor = i32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 3, 'result[2] = 3'); + + // exclusive = false and reverse = true + let tensor = i32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 3, 'result[0] = 3'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + + // exclusive = true and reverse = false + let tensor = i32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 1, 'result[2] = 1'); + + // exclusive = true and reverse = true + let tensor = i32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 3, 'result[0] = 3'); + assert((*result.data[1]).into() == 2, 'result[1] = 2'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + + } + +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = i32_tensor_2x2_helper(); + // axis = 0 + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + + // axis = 1 + let result = tensor.cumsum(1, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 5, 'result[3] = 5'); + } + + + #[test] + #[available_gas(20000000)] + fn changed_parameters() { + + // axis = 0 exclusive = false and reverse = false + let tensor = i32_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + + // axis = 0 exclusive = false and reverse = true + let tensor = i32_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + + // axis = 0 exclusive = true and reverse = false + let tensor = i32_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 1, 'result[3] = 1'); + + // axis = 0 exclusive = true and reverse = true + let tensor = i32_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + + + + + + // axis = 1 exclusive = false and reverse = false + let tensor = i32_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 5, 'result[3] = 5'); + + // axis = 1 exclusive = false and reverse = true + let tensor = i32_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 5, 'result[2] = 5'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + + // axis = 1 exclusive = true and reverse = false + let tensor = i32_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 2, 'result[3] = 2'); + + // axis = 1 exclusive = true and reverse = true + let tensor = i32_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 3, 'result[2] = 3'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + + } + + + +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = i32_tensor_2x2x2_helper(); + + // axis = 0 + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 6, 'result[5] = 6'); + assert((*result.data[6]).into() == 8, 'result[6] = 8'); + assert((*result.data[7]).into() == 10,'result[7] = 10'); + + + // axis = 1 + let result = tensor.cumsum(1, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 10, 'result[6] = 10'); + assert((*result.data[7]).into() == 12, 'result[7] = 12'); + + + // axis = 2 + let result = tensor.cumsum(2, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 5, 'result[3] = 5'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 9, 'result[5] = 9'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 13, 'result[7] = 13'); + } + + + + #[test] + #[available_gas(40000000)] + fn changed_parameters() { + + // axis = 0 exclusive = false and reverse = false + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 6, 'result[5] = 6'); + assert((*result.data[6]).into() == 8, 'result[6] = 8'); + assert((*result.data[7]).into() == 10, 'result[7] = 10'); + + // axis = 0 exclusive = false and reverse = true + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 6, 'result[1] = 6'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 10, 'result[3] = 10'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + + // axis = 0 exclusive = true and reverse = false + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + assert((*result.data[4]).into() == 0, 'result[4] = 0'); + assert((*result.data[5]).into() == 1, 'result[5] = 1'); + assert((*result.data[6]).into() == 2, 'result[6] = 2'); + assert((*result.data[7]).into() == 3, 'result[7] = 3'); + + // axis = 0 exclusive = true and reverse = true + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 5, 'result[1] = 5'); + assert((*result.data[2]).into() == 6, 'result[2] = 6'); + assert((*result.data[3]).into() == 7, 'result[3] = 7'); + assert((*result.data[4]).into() == 0, 'result[4] = 0'); + assert((*result.data[5]).into() == 0, 'result[5] = 0'); + assert((*result.data[6]).into() == 0, 'result[6] = 0'); + assert((*result.data[7]).into() == 0, 'result[7] = 0'); + + + + + + + // axis = 1 exclusive = false and reverse = false + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 10, 'result[6] = 10'); + assert((*result.data[7]).into() == 12, 'result[7] = 12'); + + + // axis = 1 exclusive = false and reverse = true + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 10, 'result[4] = 10'); + assert((*result.data[5]).into() == 12, 'result[5] = 12'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + + + // axis = 1 exclusive = true and reverse = false + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 1, 'result[3] = 1'); + assert((*result.data[4]).into() == 0, 'result[4] = 0'); + assert((*result.data[5]).into() == 0, 'result[5] = 0'); + assert((*result.data[6]).into() == 4, 'result[6] = 4'); + assert((*result.data[7]).into() == 5, 'result[7] = 5'); + + // axis = 1 exclusive = true and reverse = true + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + assert((*result.data[4]).into() == 6, 'result[4] = 6'); + assert((*result.data[5]).into() == 7, 'result[5] = 7'); + assert((*result.data[6]).into() == 0, 'result[6] = 0'); + assert((*result.data[7]).into() == 0, 'result[7] = 0'); + + + + + + + + + // axis = 2 exclusive = false and reverse = false + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 5, 'result[3] = 5'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 9, 'result[5] = 9'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 13, 'result[7] = 13'); + + + // axis = 2 exclusive = false and reverse = true + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 5, 'result[2] = 5'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 9, 'result[4] = 9'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 13, 'result[6] = 13'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + + // axis = 2 exclusive = true and reverse = false + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 2, 'result[3] = 2'); + assert((*result.data[4]).into() == 0, 'result[4] = 0'); + assert((*result.data[5]).into() == 4, 'result[5] = 4'); + assert((*result.data[6]).into() == 0, 'result[6] = 0'); + assert((*result.data[7]).into() == 6, 'result[7] = 6'); + + // axis = 2 exclusive = true and reverse = true + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 3, 'result[2] = 3'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + assert((*result.data[4]).into() == 5, 'result[4] = 5'); + assert((*result.data[5]).into() == 0, 'result[5] = 0'); + assert((*result.data[6]).into() == 7, 'result[6] = 7'); + assert((*result.data[7]).into() == 0, 'result[7] = 0'); + + } + +} diff --git a/src/tests/operators/tensor/math/cumsum/cumsum_u32_test.cairo b/src/tests/operators/tensor/math/cumsum/cumsum_u32_test.cairo new file mode 100644 index 000000000..5d13818e9 --- /dev/null +++ b/src/tests/operators/tensor/math/cumsum/cumsum_u32_test.cairo @@ -0,0 +1,389 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 3, 'result[2] = 3'); + } + + #[test] + #[available_gas(20000000)] + fn changed_parameters() { + + // exclusive = false and reverse = false + let tensor = u32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 3, 'result[2] = 3'); + + // exclusive = false and reverse = true + let tensor = u32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 3, 'result[0] = 3'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + + // exclusive = true and reverse = false + let tensor = u32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 1, 'result[2] = 1'); + + // exclusive = true and reverse = true + let tensor = u32_tensor_1x3_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 3, 'result[0] = 3'); + assert((*result.data[1]).into() == 2, 'result[1] = 2'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + + } + +} + + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = u32_tensor_2x2_helper(); + // axis = 0 + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + + // axis = 1 + let result = tensor.cumsum(1, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 5, 'result[3] = 5'); + } + + + #[test] + #[available_gas(20000000)] + fn changed_parameters() { + + // axis = 0 exclusive = false and reverse = false + let tensor = u32_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + + // axis = 0 exclusive = false and reverse = true + let tensor = u32_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + + // axis = 0 exclusive = true and reverse = false + let tensor = u32_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 1, 'result[3] = 1'); + + // axis = 0 exclusive = true and reverse = true + let tensor = u32_tensor_2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + + + + + + // axis = 1 exclusive = false and reverse = false + let tensor = u32_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 5, 'result[3] = 5'); + + // axis = 1 exclusive = false and reverse = true + let tensor = u32_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 5, 'result[2] = 5'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + + // axis = 1 exclusive = true and reverse = false + let tensor = u32_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 2, 'result[3] = 2'); + + // axis = 1 exclusive = true and reverse = true + let tensor = u32_tensor_2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 3, 'result[2] = 3'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + + } + + + +} + + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::{ArrayTrait, SpanTrait}; + use core::traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, ExtraParams}; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + + + #[test] + #[available_gas(20000000)] + fn default_parameters() { + let tensor = u32_tensor_2x2x2_helper(); + + // axis = 0 + let result = tensor.cumsum(0, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 6, 'result[5] = 6'); + assert((*result.data[6]).into() == 8, 'result[6] = 8'); + assert((*result.data[7]).into() == 10,'result[7] = 10'); + + + // axis = 1 + let result = tensor.cumsum(1, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 10, 'result[6] = 10'); + assert((*result.data[7]).into() == 12, 'result[7] = 12'); + + + // axis = 2 + let result = tensor.cumsum(2, Option::None(()), Option::None(())); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 5, 'result[3] = 5'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 9, 'result[5] = 9'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 13, 'result[7] = 13'); + } + + + + #[test] + #[available_gas(40000000)] + fn changed_parameters() { + + // axis = 0 exclusive = false and reverse = false + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 6, 'result[5] = 6'); + assert((*result.data[6]).into() == 8, 'result[6] = 8'); + assert((*result.data[7]).into() == 10, 'result[7] = 10'); + + // axis = 0 exclusive = false and reverse = true + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 6, 'result[1] = 6'); + assert((*result.data[2]).into() == 8, 'result[2] = 8'); + assert((*result.data[3]).into() == 10, 'result[3] = 10'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + + // axis = 0 exclusive = true and reverse = false + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + assert((*result.data[4]).into() == 0, 'result[4] = 0'); + assert((*result.data[5]).into() == 1, 'result[5] = 1'); + assert((*result.data[6]).into() == 2, 'result[6] = 2'); + assert((*result.data[7]).into() == 3, 'result[7] = 3'); + + // axis = 0 exclusive = true and reverse = true + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(0, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 4, 'result[0] = 4'); + assert((*result.data[1]).into() == 5, 'result[1] = 5'); + assert((*result.data[2]).into() == 6, 'result[2] = 6'); + assert((*result.data[3]).into() == 7, 'result[3] = 7'); + assert((*result.data[4]).into() == 0, 'result[4] = 0'); + assert((*result.data[5]).into() == 0, 'result[5] = 0'); + assert((*result.data[6]).into() == 0, 'result[6] = 0'); + assert((*result.data[7]).into() == 0, 'result[7] = 0'); + + + + + + + // axis = 1 exclusive = false and reverse = false + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 4, 'result[3] = 4'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 10, 'result[6] = 10'); + assert((*result.data[7]).into() == 12, 'result[7] = 12'); + + + // axis = 1 exclusive = false and reverse = true + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 4, 'result[1] = 4'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 10, 'result[4] = 10'); + assert((*result.data[5]).into() == 12, 'result[5] = 12'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + + + // axis = 1 exclusive = true and reverse = false + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 1, 'result[3] = 1'); + assert((*result.data[4]).into() == 0, 'result[4] = 0'); + assert((*result.data[5]).into() == 0, 'result[5] = 0'); + assert((*result.data[6]).into() == 4, 'result[6] = 4'); + assert((*result.data[7]).into() == 5, 'result[7] = 5'); + + // axis = 1 exclusive = true and reverse = true + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(1, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 2, 'result[0] = 2'); + assert((*result.data[1]).into() == 3, 'result[1] = 3'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + assert((*result.data[4]).into() == 6, 'result[4] = 6'); + assert((*result.data[5]).into() == 7, 'result[5] = 7'); + assert((*result.data[6]).into() == 0, 'result[6] = 0'); + assert((*result.data[7]).into() == 0, 'result[7] = 0'); + + + + + + + + + // axis = 2 exclusive = false and reverse = false + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(false), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 2, 'result[2] = 2'); + assert((*result.data[3]).into() == 5, 'result[3] = 5'); + assert((*result.data[4]).into() == 4, 'result[4] = 4'); + assert((*result.data[5]).into() == 9, 'result[5] = 9'); + assert((*result.data[6]).into() == 6, 'result[6] = 6'); + assert((*result.data[7]).into() == 13, 'result[7] = 13'); + + + // axis = 2 exclusive = false and reverse = true + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(false), Option::Some(true)); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 1, 'result[1] = 1'); + assert((*result.data[2]).into() == 5, 'result[2] = 5'); + assert((*result.data[3]).into() == 3, 'result[3] = 3'); + assert((*result.data[4]).into() == 9, 'result[4] = 9'); + assert((*result.data[5]).into() == 5, 'result[5] = 5'); + assert((*result.data[6]).into() == 13, 'result[6] = 13'); + assert((*result.data[7]).into() == 7, 'result[7] = 7'); + + // axis = 2 exclusive = true and reverse = false + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(true), Option::Some(false)); + assert((*result.data[0]).into() == 0, 'result[0] = 0'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 0, 'result[2] = 0'); + assert((*result.data[3]).into() == 2, 'result[3] = 2'); + assert((*result.data[4]).into() == 0, 'result[4] = 0'); + assert((*result.data[5]).into() == 4, 'result[5] = 4'); + assert((*result.data[6]).into() == 0, 'result[6] = 0'); + assert((*result.data[7]).into() == 6, 'result[7] = 6'); + + // axis = 2 exclusive = true and reverse = true + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.cumsum(2, Option::Some(true), Option::Some(true)); + assert((*result.data[0]).into() == 1, 'result[0] = 1'); + assert((*result.data[1]).into() == 0, 'result[1] = 0'); + assert((*result.data[2]).into() == 3, 'result[2] = 3'); + assert((*result.data[3]).into() == 0, 'result[3] = 0'); + assert((*result.data[4]).into() == 5, 'result[4] = 5'); + assert((*result.data[5]).into() == 0, 'result[5] = 0'); + assert((*result.data[6]).into() == 7, 'result[6] = 7'); + assert((*result.data[7]).into() == 0, 'result[7] = 0'); + + } + +} From 538aff4953017618a697c5842b9c06bc770ea440 Mon Sep 17 00:00:00 2001 From: Lanre Ojetokun Date: Sat, 24 Jun 2023 00:53:53 +0100 Subject: [PATCH 055/126] update docs --- docs/CHANGELOG.md | 5 ++ docs/SUMMARY.md | 1 + docs/apis/compatibility.md | 3 +- docs/apis/operators/tensor/README.md | 1 + docs/apis/operators/tensor/tensor.cumsum.md | 66 +++++++++++++++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 docs/apis/operators/tensor/tensor.cumsum.md diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 07a79e56e..e21d1ee07 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] - 2023-06-24 + +### Added +- Added cumsum operator + ## [Unreleased] - 2023-06-23 ### Changed diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index acb9390a0..ef5095919 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -33,6 +33,7 @@ * [tensor.less\_equal](apis/operators/tensor/tensor.less\_equal.md) * [tensor.abs](apis/operators/tensor/tensor.abs.md) * [tensor.ceil](apis/operators/tensor/tensor.ceil.md) + * [tensor.cumsum](apis/operators/tensor/tensor.cumsum.md) * [Neural Network](apis/operators/neural-network/README.md) * [nn.relu](apis/operators/neural-network/nn.relu.md) * [nn.leaky\_relu](apis/operators/neural-network/nn.leaky\_relu.md) diff --git a/docs/apis/compatibility.md b/docs/apis/compatibility.md index ab9b860c0..3fe3c88bc 100644 --- a/docs/apis/compatibility.md +++ b/docs/apis/compatibility.md @@ -32,6 +32,7 @@ You can see below the list of current supported ONNX Operators: | Softsign | :white_check_mark: | | Softplus | :white_check_mark: | | Linear | :white_check_mark: | +| Cumsum | :white_check_mark: | Performance optimizations: @@ -39,4 +40,4 @@ Performance optimizations: | :----------------: | :----------------: | | 8-bit quantization | :white_check_mark: | -Current Operators support: **24/156 (15%)** +Current Operators support: **27/156 (17%)** diff --git a/docs/apis/operators/tensor/README.md b/docs/apis/operators/tensor/README.md index 60792c4db..8ebec5cc7 100644 --- a/docs/apis/operators/tensor/README.md +++ b/docs/apis/operators/tensor/README.md @@ -73,6 +73,7 @@ use orion::operators::tensor::core::TensorTrait; | [`tensor.less_equal`](tensor.less\_equal.md) | Check if each element of the first tensor is less than or equal to the corresponding element of the second tensor. | | [`tensor.abs`](tensor.abs.md) | Computes the absolute value of all elements in the input tensor. | | [`tensor.ceil`](tensor.ceil.md) | Rounds up the value of each element in the input tensor. | +| [`tensor.cumsum`](tensor.cumsum.md) | Returns the cumulative sum of the elements along a given axis. | ### Arithmetic Operations diff --git a/docs/apis/operators/tensor/tensor.cumsum.md b/docs/apis/operators/tensor/tensor.cumsum.md new file mode 100644 index 000000000..91f64d6f4 --- /dev/null +++ b/docs/apis/operators/tensor/tensor.cumsum.md @@ -0,0 +1,66 @@ +# tensor.cumsum + +```rust +fn cumsum(self: @Tensor, axis: usize, exclusive: Option, reverse: Option) -> Tensor; +``` + +Performs cumulative sum of the input elements along the given axis. + +## Args + +* `self`(`@Tensor`) - The input tensor. +* `axis`(`usize`) - The axis along which to compute the cumulative sum. +* `exclusive`(`Option`) - By default, it will do the sum inclusively meaning the first element is copied as is. +* `reverse`(`Option`) - If true, the cumulative sum is performed in the opposite direction. Defaults to false. + +## Panics + +* Panics if axis is not in the range of the input tensor's dimensions. + +## Returns + +A new `Tensor` instance containing the cumulative sum of the input tensor's elements along the given axis. + +## Examples + +Case 1: cumsum with default parameters + +```rust +fn cumsum_example() -> Tensor { +// We instantiate a 3D Tensor here. +// [[[0,1],[2,3]],[[4,5],[6,7]]] +let tensor = u32_tensor_2x2x2_helper(); + +// We can call `cumsum` function as follows. +return tensor.cumsum(2,Option::None(()),Option::None(())); +} +>>> [[[0,1],[2,5]],[[4,9],[6,13]]] +``` + +Case 2: cumsum with exclusive = true + +```rust +fn cumsum_example() -> Tensor { +// We instantiate a 3D Tensor here. +// [[[0,1],[2,3]],[[4,5],[6,7]]] +let tensor = u32_tensor_2x2x2_helper(); + +// We can call `cumsum` function as follows. +return tensor.cumsum(2,Option::Some(true),Option::None(())); +} +>>> [[[0,0],[0,2]],[[0,4],[0,6]]] +``` + +Case 3: cumsum with exclusive = true and reverse = true + +```rust +fn cumsum_example() -> Tensor { +// We instantiate a 3D Tensor here. +// [[[0,1],[2,3]],[[4,5],[6,7]]] +let tensor = u32_tensor_2x2x2_helper(); + +// We can call `cumsum` function as follows. +return tensor.cumsum(2,Option::Some(true),Option::Some(true)); +} +>>> [[[1,0],[3,0]],[[5,0],[7,0]]] +``` From c2b9cf2167a460a2dd076de9f5937c86eeccfd2f Mon Sep 17 00:00:00 2001 From: Hakeem Kazeem Date: Tue, 27 Jun 2023 13:58:01 +0100 Subject: [PATCH 056/126] Sin implementation --- src/numbers.cairo | 1 + src/numbers/fixed_point/core.cairo | 2 + .../implementations/impl_16x16.cairo | 8 +- .../implementations/impl_8x23.cairo | 6 + src/numbers/fixed_point/math/math_16x16.cairo | 34 +- src/numbers/fixed_point/math/math_8x23.cairo | 31 +- src/operators.cairo | 1 + src/operators/tensor/core.cairo | 11 +- .../implementations/impl_tensor_fp.cairo | 20 +- .../implementations/impl_tensor_i32.cairo | 14 +- .../implementations/impl_tensor_u32.cairo | 15 +- src/operators/tensor/math.cairo | 1 + src/operators/tensor/math/sin.cairo | 3 + src/operators/tensor/math/sin/sin_fp.cairo | 3 + .../tensor/math/sin/sin_fp/core.cairo | 18 + .../tensor/math/sin/sin_fp/fp16x16.cairo | 28 ++ .../tensor/math/sin/sin_fp/fp8x23.cairo | 28 ++ src/operators/tensor/math/sin/sin_i32.cairo | 3 + .../tensor/math/sin/sin_i32/core.cairo | 19 + .../tensor/math/sin/sin_i32/fp16x16.cairo | 37 ++ .../tensor/math/sin/sin_i32/fp8x23.cairo | 37 ++ src/operators/tensor/math/sin/sin_u32.cairo | 3 + .../tensor/math/sin/sin_u32/core.cairo | 19 + .../tensor/math/sin/sin_u32/fp16x16.cairo | 31 ++ .../tensor/math/sin/sin_u32/fp8x23.cairo | 31 ++ src/tests.cairo | 7 +- src/tests/numbers.cairo | 2 +- src/tests/numbers/fixed_point.cairo | 2 +- .../numbers/fixed_point/fp16x16_test.cairo | 24 +- .../numbers/fixed_point/fp8x23_test.cairo | 23 +- src/tests/numbers/signed_integer_test.cairo | 449 +++++++++--------- src/tests/operators/nn.cairo | 2 +- src/tests/operators/tensor.cairo | 2 +- src/tests/operators/tensor/math.cairo | 1 + src/tests/operators/tensor/math/sin.cairo | 4 + .../tensor/math/sin/sin_fp_test.cairo | 2 + .../sin/sin_fp_test/sin_fp16x16_test.cairo | 84 ++++ .../sin/sin_fp_test/sin_fp8x23_test.cairo | 84 ++++ .../tensor/math/sin/sin_i32_test.cairo | 84 ++++ .../tensor/math/sin/sin_u32_test.cairo | 80 ++++ 40 files changed, 1009 insertions(+), 245 deletions(-) create mode 100644 src/operators/tensor/math/sin.cairo create mode 100644 src/operators/tensor/math/sin/sin_fp.cairo create mode 100644 src/operators/tensor/math/sin/sin_fp/core.cairo create mode 100644 src/operators/tensor/math/sin/sin_fp/fp16x16.cairo create mode 100644 src/operators/tensor/math/sin/sin_fp/fp8x23.cairo create mode 100644 src/operators/tensor/math/sin/sin_i32.cairo create mode 100644 src/operators/tensor/math/sin/sin_i32/core.cairo create mode 100644 src/operators/tensor/math/sin/sin_i32/fp16x16.cairo create mode 100644 src/operators/tensor/math/sin/sin_i32/fp8x23.cairo create mode 100644 src/operators/tensor/math/sin/sin_u32.cairo create mode 100644 src/operators/tensor/math/sin/sin_u32/core.cairo create mode 100644 src/operators/tensor/math/sin/sin_u32/fp16x16.cairo create mode 100644 src/operators/tensor/math/sin/sin_u32/fp8x23.cairo create mode 100644 src/tests/operators/tensor/math/sin.cairo create mode 100644 src/tests/operators/tensor/math/sin/sin_fp_test.cairo create mode 100644 src/tests/operators/tensor/math/sin/sin_fp_test/sin_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/math/sin/sin_fp_test/sin_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/math/sin/sin_i32_test.cairo create mode 100644 src/tests/operators/tensor/math/sin/sin_u32_test.cairo diff --git a/src/numbers.cairo b/src/numbers.cairo index fdbf79664..33d5f87bc 100644 --- a/src/numbers.cairo +++ b/src/numbers.cairo @@ -1,2 +1,3 @@ mod fixed_point; mod signed_integer; + diff --git a/src/numbers/fixed_point/core.cairo b/src/numbers/fixed_point/core.cairo index 58d939f18..027c79460 100644 --- a/src/numbers/fixed_point/core.cairo +++ b/src/numbers/fixed_point/core.cairo @@ -481,4 +481,6 @@ trait FixedTrait { /// ``` /// fn sqrt(self: FixedType) -> FixedType; + + fn sin(self: FixedType) -> FixedType; } diff --git a/src/numbers/fixed_point/implementations/impl_16x16.cairo b/src/numbers/fixed_point/implementations/impl_16x16.cairo index 943df4761..2e8f59869 100644 --- a/src/numbers/fixed_point/implementations/impl_16x16.cairo +++ b/src/numbers/fixed_point/implementations/impl_16x16.cairo @@ -13,6 +13,9 @@ const ONE_u64: u64 = 65536; // 2 ** 16 const HALF: u128 = 32768; // 2 ** 15 const MAX: u128 = 4294967295; // 2 ** 32 - 1 const MIN_MAG: u128 = 4294967296; // 2 ** 32 +const PI: u128 = 205887_u128; +const HALF_PI: u128 = 102943_u128; + /// IMPLS @@ -77,10 +80,13 @@ impl FP16x16Impl of FixedTrait { return math_16x16::round(self); } - fn sqrt(self: FixedType) -> FixedType { return math_16x16::sqrt(self); } + + fn sin(self: FixedType) -> FixedType { + return math_16x16::sin(self); + } } impl FP16x16Print of PrintTrait { diff --git a/src/numbers/fixed_point/implementations/impl_8x23.cairo b/src/numbers/fixed_point/implementations/impl_8x23.cairo index 97428ddf3..a290e3f2c 100644 --- a/src/numbers/fixed_point/implementations/impl_8x23.cairo +++ b/src/numbers/fixed_point/implementations/impl_8x23.cairo @@ -13,6 +13,8 @@ const ONE_u64: u64 = 8388608; // 2 ** 23 const HALF: u128 = 4194304; // 2 ** 22 const MAX: u128 = 2147483647; // 2 ** 31 - 1 const MIN_MAG: u128 = 2147483648; // 2 ** 31 +const PI: u128 = 26353589_u128; +const HALF_PI: u128 = 13176794_u128; /// IMPLS @@ -81,6 +83,10 @@ impl FP8x23Impl of FixedTrait { fn sqrt(self: FixedType) -> FixedType { return math_8x23::sqrt(self); } + + fn sin(self: FixedType) -> FixedType { + return math_8x23::sin(self); + } } impl FP8x23Print of PrintTrait { diff --git a/src/numbers/fixed_point/math/math_16x16.cairo b/src/numbers/fixed_point/math/math_16x16.cairo index 9b8354928..a88998ec0 100644 --- a/src/numbers/fixed_point/math/math_16x16.cairo +++ b/src/numbers/fixed_point/math/math_16x16.cairo @@ -1,6 +1,9 @@ +use core::debug::PrintTrait; use traits::Into; -use orion::numbers::fixed_point::implementations::impl_16x16::{ONE, ONE_u64, MAX, HALF}; +use orion::numbers::fixed_point::implementations::impl_16x16::{ + ONE, ONE_u64, MAX, HALF, PI, HALF_PI +}; use orion::numbers::fixed_point::implementations::impl_16x16::{ FP16x16Impl, FP16x16Add, FP16x16AddEq, FP16x16Into, FP16x16Print, FP16x16PartialEq, FP16x16Sub, FP16x16SubEq, FP16x16Mul, FP16x16MulEq, FP16x16Div, FP16x16DivEq, FP16x16PartialOrd, FP16x16Neg @@ -339,6 +342,35 @@ fn sqrt(a: FixedType) -> FixedType { return FixedTrait::new(res_u64.into(), false); } +fn sin(a: FixedType) -> FixedType { + let a1_u128 = a.mag % (2_u128 * PI); + let whole_rem = a1_u128 / PI; + let a2 = FixedType { mag: a1_u128 % PI, sign: false }; + let mut partial_sign = false; + + if (whole_rem == 1_u128) { + partial_sign = true; + } + + let acc = FixedType { mag: ONE, sign: false }; + let loop_res = a2 * _sin_loop(a2, 7_u128, acc); + let res_sign = a.sign ^ partial_sign; + return FixedType { mag: loop_res.mag, sign: res_sign }; +} + +// Helper function to calculate Taylor series for sin +fn _sin_loop(a: FixedType, i: u128, acc: FixedType) -> FixedType { + let div_u128 = (2_u128 * i + 2_u128) * (2_u128 * i + 3_u128); + let term = a * a * acc / FixedTrait::new_unscaled(div_u128, false); + let new_acc = FixedTrait::new(ONE, false) - term; + + if (i == 0_u128) { + return new_acc; + } + + return _sin_loop(a, i - 1_u128, new_acc); +} + /// Subtracts one fixed point number from another. /// /// # Arguments diff --git a/src/numbers/fixed_point/math/math_8x23.cairo b/src/numbers/fixed_point/math/math_8x23.cairo index 658d0c86b..52db7713b 100644 --- a/src/numbers/fixed_point/math/math_8x23.cairo +++ b/src/numbers/fixed_point/math/math_8x23.cairo @@ -1,6 +1,6 @@ use traits::Into; -use orion::numbers::fixed_point::implementations::impl_8x23::{ONE, ONE_u64, MAX, HALF}; +use orion::numbers::fixed_point::implementations::impl_8x23::{ONE, ONE_u64, MAX, HALF, PI, HALF_PI}; use orion::numbers::fixed_point::implementations::impl_8x23::{ FP8x23Impl, FP8x23Add, FP8x23AddEq, FP8x23Into, FP8x23Print, FP8x23PartialEq, FP8x23Sub, FP8x23SubEq, FP8x23Mul, FP8x23MulEq, FP8x23Div, FP8x23DivEq, FP8x23PartialOrd, FP8x23Neg @@ -341,6 +341,35 @@ fn sqrt(a: FixedType) -> FixedType { return FixedTrait::new(res_u64.into(), false); } + +fn sin(a: FixedType) -> FixedType { + let a1_u128 = a.mag % (2_u128 * PI); + let whole_rem = a1_u128 / PI; + let a2 = FixedType { mag: a1_u128 % PI, sign: false }; + let mut partial_sign = false; + + if (whole_rem == 1_u128) { + partial_sign = true; + } + + let acc = FixedType { mag: ONE, sign: false }; + let loop_res = a2 * _sin_loop(a2, 7_u128, acc); + let res_sign = a.sign ^ partial_sign; + return FixedType { mag: loop_res.mag, sign: res_sign }; +} + +// Helper function to calculate Taylor series for sin +fn _sin_loop(a: FixedType, i: u128, acc: FixedType) -> FixedType { + let div_u128 = (2_u128 * i + 2_u128) * (2_u128 * i + 3_u128); + let term = a * a * acc / FixedTrait::new_unscaled(div_u128, false); + let new_acc = FixedTrait::new(ONE, false) - term; + + if (i == 0_u128) { + return new_acc; + } + + return _sin_loop(a, i - 1_u128, new_acc); +} /// Subtracts one fixed point number from another. /// /// # Arguments diff --git a/src/operators.cairo b/src/operators.cairo index 417995c32..989bc1209 100644 --- a/src/operators.cairo +++ b/src/operators.cairo @@ -1,2 +1,3 @@ mod tensor; mod nn; + diff --git a/src/operators/tensor/core.cairo b/src/operators/tensor/core.cairo index 571b4e95f..5cffdd596 100644 --- a/src/operators/tensor/core.cairo +++ b/src/operators/tensor/core.cairo @@ -535,7 +535,9 @@ trait TensorTrait { /// >>> [[[1,1],[1,1]]] /// ``` /// - fn argmax(self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option) -> Tensor; + fn argmax( + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option + ) -> Tensor; /// # tensor.argmin /// /// ```rust @@ -603,7 +605,9 @@ trait TensorTrait { /// >>> [[[0,0],[1,1]]] /// ``` /// - fn argmin(self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option) -> Tensor; + fn argmin( + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option + ) -> Tensor; /// # tensor.matmul /// /// ```rust @@ -1116,6 +1120,8 @@ trait TensorTrait { /// ``` /// fn ceil(self: @Tensor) -> Tensor; + + fn sin(self: @Tensor) -> Tensor; } /// Cf: TensorTrait::new docstring @@ -1219,3 +1225,4 @@ fn at_tensor(self: @Tensor, indices: Span) -> @T { return data.at(ravel_index(*self.shape, indices)); } + diff --git a/src/operators/tensor/implementations/impl_tensor_fp.cairo b/src/operators/tensor/implementations/impl_tensor_fp.cairo index 4920501a0..63af5b50c 100644 --- a/src/operators/tensor/implementations/impl_tensor_fp.cairo +++ b/src/operators/tensor/implementations/impl_tensor_fp.cairo @@ -29,6 +29,8 @@ use orion::operators::tensor::math::greater::greater_fp::core::greater; use orion::operators::tensor::math::greater_equal::greater_equal_fp::core::greater_equal; use orion::utils::check_gas; +use orion::operators::tensor::math::sin::sin_fp::core::sin; + impl Tensor_fp of TensorTrait { fn new( shape: Span, data: Span, extra: Option @@ -68,11 +70,21 @@ impl Tensor_fp of TensorTrait { reduce_sum(self, axis, keepdims).unwrap() } - fn argmax(self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option) -> Tensor { + fn argmax( + self: @Tensor, + axis: usize, + keepdims: Option, + select_last_index: Option + ) -> Tensor { argmax(self, axis, keepdims, select_last_index).unwrap() } - fn argmin(self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option) -> Tensor { + fn argmin( + self: @Tensor, + axis: usize, + keepdims: Option, + select_last_index: Option + ) -> Tensor { argmin(self, axis, keepdims, select_last_index).unwrap() } @@ -119,6 +131,10 @@ impl Tensor_fp of TensorTrait { fn ceil(self: @Tensor) -> Tensor { ceil(self).unwrap() } + + fn sin(self: @Tensor) -> Tensor { + sin(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_i32.cairo b/src/operators/tensor/implementations/impl_tensor_i32.cairo index 4b6ccfd21..0cf1571e6 100644 --- a/src/operators/tensor/implementations/impl_tensor_i32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_i32.cairo @@ -30,6 +30,8 @@ use orion::operators::tensor::math::ln::ln_i32::core::ln_i32; use orion::operators::tensor::math::arithmetic::arithmetic_i32::{add, sub, mul, div}; use orion::utils::check_gas; +use orion::operators::tensor::math::sin::sin_i32::core::sin_i32; + impl Tensor_i32 of TensorTrait { fn new(shape: Span, data: Span, extra: Option) -> Tensor { new_tensor(shape, data, extra) @@ -67,11 +69,15 @@ impl Tensor_i32 of TensorTrait { reduce_sum(self, axis, keepdims) } - fn argmax(self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option) -> Tensor { + fn argmax( + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option + ) -> Tensor { argmax(self, axis, keepdims, select_last_index) } - fn argmin(self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option) -> Tensor { + fn argmin( + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option + ) -> Tensor { argmin(self, axis, keepdims, select_last_index) } @@ -118,6 +124,10 @@ impl Tensor_i32 of TensorTrait { fn ceil(self: @Tensor) -> Tensor { ceil(self) } + + fn sin(self: @Tensor) -> Tensor { + sin_i32(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_u32.cairo b/src/operators/tensor/implementations/impl_tensor_u32.cairo index 9c0ca8838..1aaa7516c 100644 --- a/src/operators/tensor/implementations/impl_tensor_u32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_u32.cairo @@ -29,6 +29,9 @@ use orion::operators::tensor::math::ln::ln_u32::core::ln_u32; use orion::operators::tensor::math::arithmetic::arithmetic_u32::{add, sub, mul, div}; use orion::utils::check_gas; +use orion::operators::tensor::math::sin::sin_u32::core::sin_u32; + + impl Tensor_u32 of TensorTrait { fn new(shape: Span, data: Span, extra: Option) -> Tensor { new_tensor(shape, data, extra) @@ -66,11 +69,15 @@ impl Tensor_u32 of TensorTrait { reduce_sum(self, axis, keepdims) } - fn argmax(self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option) -> Tensor { + fn argmax( + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option + ) -> Tensor { argmax(self, axis, keepdims, select_last_index) } - fn argmin(self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option) -> Tensor { + fn argmin( + self: @Tensor, axis: usize, keepdims: Option, select_last_index: Option + ) -> Tensor { argmin(self, axis, keepdims, select_last_index) } @@ -118,6 +125,10 @@ impl Tensor_u32 of TensorTrait { fn ceil(self: @Tensor) -> Tensor { ceil(self) } + + fn sin(self: @Tensor) -> Tensor { + sin_u32(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/math.cairo b/src/operators/tensor/math.cairo index b73d95f4b..61bb90abe 100644 --- a/src/operators/tensor/math.cairo +++ b/src/operators/tensor/math.cairo @@ -13,3 +13,4 @@ mod less; mod less_equal; mod abs; mod ceil; +mod sin; diff --git a/src/operators/tensor/math/sin.cairo b/src/operators/tensor/math/sin.cairo new file mode 100644 index 000000000..82cdfb23f --- /dev/null +++ b/src/operators/tensor/math/sin.cairo @@ -0,0 +1,3 @@ +mod sin_i32; +mod sin_u32; +mod sin_fp; diff --git a/src/operators/tensor/math/sin/sin_fp.cairo b/src/operators/tensor/math/sin/sin_fp.cairo new file mode 100644 index 000000000..50d44d68c --- /dev/null +++ b/src/operators/tensor/math/sin/sin_fp.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; diff --git a/src/operators/tensor/math/sin/sin_fp/core.cairo b/src/operators/tensor/math/sin/sin_fp/core.cairo new file mode 100644 index 000000000..37782248e --- /dev/null +++ b/src/operators/tensor/math/sin/sin_fp/core.cairo @@ -0,0 +1,18 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::operators::tensor::math::sin::sin_fp::fp8x23; +use orion::operators::tensor::math::sin::sin_fp::fp16x16; + +/// Cf: TensorTrait::sin docstring +fn sin(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::sin(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::sin(self)), + }, + Option::None(_) => Option::Some(fp16x16::sin(self)), + }, + Option::None(_) => Option::Some(fp16x16::sin(self)), + } +} diff --git a/src/operators/tensor/math/sin/sin_fp/fp16x16.cairo b/src/operators/tensor/math/sin/sin_fp/fp16x16.cairo new file mode 100644 index 000000000..9e0594f9e --- /dev/null +++ b/src/operators/tensor/math/sin/sin_fp/fp16x16.cairo @@ -0,0 +1,28 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::exp docstring +fn sin(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + result.append(FixedTrait::sin(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sin/sin_fp/fp8x23.cairo b/src/operators/tensor/math/sin/sin_fp/fp8x23.cairo new file mode 100644 index 000000000..c2b73c907 --- /dev/null +++ b/src/operators/tensor/math/sin/sin_fp/fp8x23.cairo @@ -0,0 +1,28 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::exp docstring +fn sin(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + result.append(FixedTrait::sin(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sin/sin_i32.cairo b/src/operators/tensor/math/sin/sin_i32.cairo new file mode 100644 index 000000000..50d44d68c --- /dev/null +++ b/src/operators/tensor/math/sin/sin_i32.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; diff --git a/src/operators/tensor/math/sin/sin_i32/core.cairo b/src/operators/tensor/math/sin/sin_i32/core.cairo new file mode 100644 index 000000000..88f7ffa30 --- /dev/null +++ b/src/operators/tensor/math/sin/sin_i32/core.cairo @@ -0,0 +1,19 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::math::sin::sin_i32::fp8x23; +use orion::operators::tensor::math::sin::sin_i32::fp16x16; + +/// Cf: TensorTrait::sin docstring +fn sin_i32(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::sin(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::sin(self)), + }, + Option::None(_) => Option::Some(fp16x16::sin(self)), + }, + Option::None(_) => Option::Some(fp16x16::sin(self)), + } +} diff --git a/src/operators/tensor/math/sin/sin_i32/fp16x16.cairo b/src/operators/tensor/math/sin/sin_i32/fp16x16.cairo new file mode 100644 index 000000000..ab161e631 --- /dev/null +++ b/src/operators/tensor/math/sin/sin_i32/fp16x16.cairo @@ -0,0 +1,37 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::exp docstring +fn sin(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + + if ele.sign == true { + let ele = FixedTrait::from_unscaled_felt((ele.mag).into() * -1); + result.append(FixedTrait::sin(ele)) + } else { + let ele = FixedTrait::from_unscaled_felt((ele.mag).into()); + result.append(FixedTrait::sin(ele)) + } + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sin/sin_i32/fp8x23.cairo b/src/operators/tensor/math/sin/sin_i32/fp8x23.cairo new file mode 100644 index 000000000..215b72c1b --- /dev/null +++ b/src/operators/tensor/math/sin/sin_i32/fp8x23.cairo @@ -0,0 +1,37 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::exp docstring +fn sin(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + + if ele.sign == true { + let ele = FixedTrait::from_unscaled_felt((ele.mag).into() * -1); + result.append(FixedTrait::sin(ele)) + } else { + let ele = FixedTrait::from_unscaled_felt((ele.mag).into()); + result.append(FixedTrait::sin(ele)) + } + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sin/sin_u32.cairo b/src/operators/tensor/math/sin/sin_u32.cairo new file mode 100644 index 000000000..50d44d68c --- /dev/null +++ b/src/operators/tensor/math/sin/sin_u32.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; diff --git a/src/operators/tensor/math/sin/sin_u32/core.cairo b/src/operators/tensor/math/sin/sin_u32/core.cairo new file mode 100644 index 000000000..4ced3846b --- /dev/null +++ b/src/operators/tensor/math/sin/sin_u32/core.cairo @@ -0,0 +1,19 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::math::sin::sin_u32::fp8x23; +use orion::operators::tensor::math::sin::sin_u32::fp16x16; + +/// Cf: TensorTrait::sin docstring +fn sin_u32(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::sin(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::sin(self)), + }, + Option::None(_) => Option::Some(fp16x16::sin(self)), + }, + Option::None(_) => Option::Some(fp16x16::sin(self)), + } +} diff --git a/src/operators/tensor/math/sin/sin_u32/fp16x16.cairo b/src/operators/tensor/math/sin/sin_u32/fp16x16.cairo new file mode 100644 index 000000000..af3dfd4db --- /dev/null +++ b/src/operators/tensor/math/sin/sin_u32/fp16x16.cairo @@ -0,0 +1,31 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::exp docstring +fn sin(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = FixedTrait::from_unscaled_felt((*data.pop_front().unwrap()).into()); + + result.append(FixedTrait::sin(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sin/sin_u32/fp8x23.cairo b/src/operators/tensor/math/sin/sin_u32/fp8x23.cairo new file mode 100644 index 000000000..571be75c2 --- /dev/null +++ b/src/operators/tensor/math/sin/sin_u32/fp8x23.cairo @@ -0,0 +1,31 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::exp docstring +fn sin(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = FixedTrait::from_unscaled_felt((*data.pop_front().unwrap()).into()); + + result.append(FixedTrait::sin(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/tests.cairo b/src/tests.cairo index c142d6926..3f9537c1e 100644 --- a/src/tests.cairo +++ b/src/tests.cairo @@ -1,4 +1,5 @@ -mod numbers; -mod performance; +// mod numbers; +// mod performance; mod operators; -mod helpers; \ No newline at end of file +mod helpers; + diff --git a/src/tests/numbers.cairo b/src/tests/numbers.cairo index 276bd20e5..248dadb20 100644 --- a/src/tests/numbers.cairo +++ b/src/tests/numbers.cairo @@ -1,2 +1,2 @@ mod fixed_point; -mod signed_integer_test; \ No newline at end of file +mod signed_integer_test; diff --git a/src/tests/numbers/fixed_point.cairo b/src/tests/numbers/fixed_point.cairo index c2919d602..78b4519be 100644 --- a/src/tests/numbers/fixed_point.cairo +++ b/src/tests/numbers/fixed_point.cairo @@ -1,2 +1,2 @@ mod fp8x23_test; -mod fp16x16_test; \ No newline at end of file +mod fp16x16_test; diff --git a/src/tests/numbers/fixed_point/fp16x16_test.cairo b/src/tests/numbers/fixed_point/fp16x16_test.cairo index ec1233693..2a8b2f176 100644 --- a/src/tests/numbers/fixed_point/fp16x16_test.cairo +++ b/src/tests/numbers/fixed_point/fp16x16_test.cairo @@ -1,14 +1,15 @@ use option::OptionTrait; use traits::Into; +use debug::PrintTrait; + use orion::numbers::fixed_point::implementations::impl_16x16::{ ONE, _felt_abs, _felt_sign, FP16x16Impl, FP16x16Into, FP16x16Add, FP16x16AddEq, FP16x16Sub, FP16x16SubEq, FP16x16Mul, FP16x16MulEq, FP16x16Div, FP16x16DivEq, FP16x16PartialOrd, - FP16x16PartialEq + FP16x16PartialEq, PI, HALF_PI }; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::core; - #[test] fn test_into() { let a = FixedTrait::from_unscaled_felt(5); @@ -323,3 +324,22 @@ fn test_gt() { assert(c > b == false, 'c > b'); assert(c > c == false, 'c > c'); } + +#[test] +#[available_gas(10000000)] +fn test_sin() { + let a = FixedTrait::new(HALF_PI, false); + assert(a.sin().into() == 65536, 'invalid half pi'); + + let a = FixedTrait::new(HALF_PI / 2_u128, false); + assert(a.sin().into() == 46340, 'invalid quarter pi'); // 0.7071067811865475 + + let a = FixedTrait::new(PI, false); + assert(a.sin().into() == 0, 'invalid pi'); + + let a = FixedTrait::new(HALF_PI, true); + assert(a.sin().into() == -65536, 'invalid neg half pi'); // 0.9999999999939766 + + let a = FixedTrait::new_unscaled(17_u128, false); + assert(a.sin().into() == -63007, 'invalid 17'); +} diff --git a/src/tests/numbers/fixed_point/fp8x23_test.cairo b/src/tests/numbers/fixed_point/fp8x23_test.cairo index a7d60c7c6..232feec8e 100644 --- a/src/tests/numbers/fixed_point/fp8x23_test.cairo +++ b/src/tests/numbers/fixed_point/fp8x23_test.cairo @@ -1,10 +1,12 @@ use option::OptionTrait; use traits::Into; +use debug::PrintTrait; use orion::numbers::fixed_point::implementations::impl_8x23::{ ONE, _felt_abs, _felt_sign, FP8x23Impl, FP8x23Into, FP8x23Add, FP8x23AddEq, FP8x23Sub, - FP8x23SubEq, FP8x23Mul, FP8x23MulEq, FP8x23Div, FP8x23DivEq, FP8x23PartialOrd, FP8x23PartialEq + FP8x23SubEq, FP8x23Mul, FP8x23MulEq, FP8x23Div, FP8x23DivEq, FP8x23PartialOrd, FP8x23PartialEq, + PI, HALF_PI }; use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; use orion::numbers::fixed_point::core; @@ -323,3 +325,22 @@ fn test_gt() { assert(c > b == false, 'c > b'); assert(c > c == false, 'c > c'); } + +#[test] +#[available_gas(10000000)] +fn test_sin() { + let a = FixedTrait::new(HALF_PI, false); + assert(a.sin().into() == 8388608, 'invalid half pi'); + + let a = FixedTrait::new(HALF_PI / 2_u128, false); + assert(a.sin().into() == 5931641, 'invalid quarter pi'); // 0.7071067811865475 + + let a = FixedTrait::new(PI, false); + assert(a.sin().into() == 0, 'invalid pi'); + + let a = FixedTrait::new(HALF_PI, true); + assert(a.sin().into() == -8388608, 'invalid neg half pi'); // 0.9999999999939766 + + let a = FixedTrait::new_unscaled(17_u128, false); + assert(a.sin().into() == -8064787, 'invalid 17'); // -0.9613974918795568 +} diff --git a/src/tests/numbers/signed_integer_test.cairo b/src/tests/numbers/signed_integer_test.cairo index f964f3a03..cc0995594 100644 --- a/src/tests/numbers/signed_integer_test.cairo +++ b/src/tests/numbers/signed_integer_test.cairo @@ -1,224 +1,225 @@ -use core::traits::Into; -use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; - -#[test] -fn test_into() { - let x = IntegerTrait::::new(42, false); - assert(x.into() == 42, 'should convert to felt252'); - let x = IntegerTrait::::new(42, true); - assert(x.into() == -42, 'should convert to felt252'); -} - -#[test] -fn test_add() { - // Test addition of two positive integers - let a = IntegerTrait::::new(42, false); - let b = IntegerTrait::::new(13, false); - let result = a + b; - assert(result.mag == 55, '42 + 13 = 55'); - assert(result.sign == false, '42 + 13 -> positive'); - - // Test addition of two negative integers - let a = IntegerTrait::::new(42, true); - let b = IntegerTrait::::new(13, true); - let result = a + b; - assert(result.mag == 55, '-42 - 13 = -55'); - assert(result.sign == true, '-42 - 13 -> negative'); - - // Test addition of a positive integer and a negative integer with the same magnitude - - let a = IntegerTrait::::new(42, false); - let b = IntegerTrait::::new(42, true); - let result = a + b; - assert(result.mag == 0, '42 - 42 = 0'); - assert(result.sign == false, '42 - 42 -> positive'); - - // Test addition of a positive integer and a negative integer with different magnitudes - let a = IntegerTrait::::new(42, false); - let b = IntegerTrait::::new(13, true); - let result = a + b; - assert(result.mag == 29, '42 - 13 = 29'); - assert(result.sign == false, '42 - 13 -> positive'); - - // Test addition of a negative integer and a positive integer with different magnitudes - let a = IntegerTrait::::new(42, true); - let b = IntegerTrait::::new(13, false); - let result = a + b; - assert(result.mag == 29, '-42 + 13 = -29'); - assert(result.sign == true, '-42 + 13 -> negative'); -} - -#[test] -fn test_sub() { - // Test subtraction of two positive integers with larger first - let a = IntegerTrait::::new(42, false); - let b = IntegerTrait::::new(13, false); - let result = a - b; - assert(result.mag == 29, '42 - 13 = 29'); - assert(result.sign == false, '42 - 13 -> positive'); - - // Test subtraction of two positive integers with larger second - let a = IntegerTrait::::new(13, false); - let b = IntegerTrait::::new(42, false); - let result = a - b; - assert(result.mag == 29, '13 - 42 = -29'); - assert(result.sign == true, '13 - 42 -> negative'); - - // Test subtraction of two negative integers with larger first - let a = IntegerTrait::::new(42, true); - let b = IntegerTrait::::new(13, true); - let result = a - b; - assert(result.mag == 29, '-42 - -13 = 29'); - assert(result.sign == true, '-42 - -13 -> negative'); - - // Test subtraction of two negative integers with larger second - let a = IntegerTrait::::new(13, true); - let b = IntegerTrait::::new(42, true); - let result = a - b; - assert(result.mag == 29, '-13 - -42 = 29'); - assert(result.sign == false, '-13 - -42 -> positive'); - - // Test subtraction of a positive integer and a negative integer with the same magnitude - let a = IntegerTrait::::new(42, false); - let b = IntegerTrait::::new(42, true); - let result = a - b; - assert(result.mag == 84, '42 - -42 = 84'); - assert(result.sign == false, '42 - -42 -> postive'); - - // Test subtraction of a negative integer and a positive integer with the same magnitude - let a = IntegerTrait::::new(42, true); - let b = IntegerTrait::::new(42, false); - let result = a - b; - assert(result.mag == 84, '-42 - 42 = -84'); - assert(result.sign == true, '-42 - 42 -> negative'); - - // Test subtraction of a positive integer and a negative integer with different magnitudes - let a = IntegerTrait::::new(100, false); - let b = IntegerTrait::::new(42, true); - let result = a - b; - assert(result.mag == 142, '100 - - 42 = 142'); - assert(result.sign == false, '100 - - 42 -> postive'); - - // Test subtraction of a negative integer and a positive integer with different magnitudes - let a = IntegerTrait::::new(42, true); - let b = IntegerTrait::::new(100, false); - let result = a - b; - assert(result.mag == 142, '-42 - 100 = -142'); - assert(result.sign == true, '-42 - 100 -> negative'); - - // Test subtraction resulting in zero - let a = IntegerTrait::::new(42, false); - let b = IntegerTrait::::new(42, false); - let result = a - b; - assert(result.mag == 0, '42 - 42 = 0'); - assert(result.sign == false, '42 - 42 -> positive'); -} - - -#[test] -fn test_mul() { - // Test multiplication of positive integers - let a = IntegerTrait::::new(10, false); - let b = IntegerTrait::::new(5, false); - let result = a * b; - assert(result.mag == 50, '10 * 5 = 50'); - assert(result.sign == false, '10 * 5 -> positive'); - - // Test multiplication of negative integers - let a = IntegerTrait::::new(10, true); - let b = IntegerTrait::::new(5, true); - let result = a * b; - assert(result.mag == 50, '-10 * -5 = 50'); - assert(result.sign == false, '-10 * -5 -> positive'); - - // Test multiplication of positive and negative integers - let a = IntegerTrait::::new(10, false); - let b = IntegerTrait::::new(5, true); - let result = a * b; - assert(result.mag == 50, '10 * -5 = -50'); - assert(result.sign == true, '10 * -5 -> negative'); - - // Test multiplication by zero - let a = IntegerTrait::::new(10, false); - let b = IntegerTrait::::new(0, false); - let result = a * b; - assert(result.mag == 0, '10 * 0 = 0'); - assert(result.sign == false, '10 * 0 -> positive'); -} - -#[test] -fn test_div_no_rem() { - // Test division of positive integers - let a = IntegerTrait::::new(10, false); - let b = IntegerTrait::::new(5, false); - let result = a / b; - assert(result.mag == 2, '10 // 5 = 2'); - assert(result.sign == false, '10 // 5 -> positive'); - - // Test division of negative integers - let a = IntegerTrait::::new(10, true); - let b = IntegerTrait::::new(5, true); - let result = a / b; - assert(result.mag == 2, '-10 // -5 = 2'); - assert(result.sign == false, '-10 // -5 -> positive'); - - // Test division of positive and negative integers - let a = IntegerTrait::::new(10, false); - let b = IntegerTrait::::new(5, true); - let result = a / b; - assert(result.mag == 2, '10 // -5 = -2'); - assert(result.sign == true, '10 // -5 -> negative'); - - // Test division with a = zero - let a = IntegerTrait::::new(0, false); - let b = IntegerTrait::::new(10, false); - let result = a / b; - assert(result.mag == 0, '0 // 10 = 0'); - assert(result.sign == false, '0 // 10 -> positive'); - - // Test division with a = zero - let a = IntegerTrait::::new(0, false); - let b = IntegerTrait::::new(10, false); - let result = a / b; - assert(result.mag == 0, '0 // 10 = 0'); - assert(result.sign == false, '0 // 10 -> positive'); -} - -#[test] -#[available_gas(20000000)] -fn test_div_rem() { - // Test division and remainder of positive integers - let a = IntegerTrait::::new(13, false); - let b = IntegerTrait::::new(5, false); - let (q, r) = a.div_rem(b); - assert(q.mag == 2 && r.mag == 3, '13 // 5 = 2 r 3'); - assert((q.sign == false) & (r.sign == false), '13 // 5 -> positive'); - - // Test division and remainder of negative integers - let a = IntegerTrait::::new(13, true); - let b = IntegerTrait::::new(5, true); - let (q, r) = a.div_rem(b); - assert(q.mag == 2 && r.mag == 3, '-13 // -5 = 2 r -3'); - assert(q.sign == false && r.sign == true, '-13 // -5 -> positive'); - - // Test division and remainder of positive and negative integers - let a = IntegerTrait::::new(13, false); - let b = IntegerTrait::::new(5, true); - let (q, r) = a.div_rem(b); - assert(q.mag == 3 && r.mag == 2, '13 // -5 = -3 r -2'); - assert(q.sign == true && r.sign == true, '13 // -5 -> negative'); - - // Test division with a = zero - let a = IntegerTrait::::new(0, false); - let b = IntegerTrait::::new(10, false); - let (q, r) = a.div_rem(b); - assert(q.mag == 0 && r.mag == 0, '0 // 10 = 0 r 0'); - assert(q.sign == false && r.sign == false, '0 // 10 -> positive'); - - // Test division and remainder with a negative dividend and positive divisor - let a = IntegerTrait::::new(13, true); - let b = IntegerTrait::::new(5, false); - let (q, r) = a.div_rem(b); - assert(q.mag == 3 && r.mag == 2, '-13 // 5 = -3 r 2'); - assert(q.sign == true && r.sign == false, '-13 // 5 -> negative'); -} +// use core::traits::Into; +// use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + +// #[test] +// fn test_into() { +// let x = IntegerTrait::::new(42, false); +// assert(x.into() == 42, 'should convert to felt252'); +// let x = IntegerTrait::::new(42, true); +// assert(x.into() == -42, 'should convert to felt252'); +// } + +// #[test] +// fn test_add() { +// // Test addition of two positive integers +// let a = IntegerTrait::::new(42, false); +// let b = IntegerTrait::::new(13, false); +// let result = a + b; +// assert(result.mag == 55, '42 + 13 = 55'); +// assert(result.sign == false, '42 + 13 -> positive'); + +// // Test addition of two negative integers +// let a = IntegerTrait::::new(42, true); +// let b = IntegerTrait::::new(13, true); +// let result = a + b; +// assert(result.mag == 55, '-42 - 13 = -55'); +// assert(result.sign == true, '-42 - 13 -> negative'); + +// // Test addition of a positive integer and a negative integer with the same magnitude + +// let a = IntegerTrait::::new(42, false); +// let b = IntegerTrait::::new(42, true); +// let result = a + b; +// assert(result.mag == 0, '42 - 42 = 0'); +// assert(result.sign == false, '42 - 42 -> positive'); + +// // Test addition of a positive integer and a negative integer with different magnitudes +// let a = IntegerTrait::::new(42, false); +// let b = IntegerTrait::::new(13, true); +// let result = a + b; +// assert(result.mag == 29, '42 - 13 = 29'); +// assert(result.sign == false, '42 - 13 -> positive'); + +// // Test addition of a negative integer and a positive integer with different magnitudes +// let a = IntegerTrait::::new(42, true); +// let b = IntegerTrait::::new(13, false); +// let result = a + b; +// assert(result.mag == 29, '-42 + 13 = -29'); +// assert(result.sign == true, '-42 + 13 -> negative'); +// } + +// #[test] +// fn test_sub() { +// // Test subtraction of two positive integers with larger first +// let a = IntegerTrait::::new(42, false); +// let b = IntegerTrait::::new(13, false); +// let result = a - b; +// assert(result.mag == 29, '42 - 13 = 29'); +// assert(result.sign == false, '42 - 13 -> positive'); + +// // Test subtraction of two positive integers with larger second +// let a = IntegerTrait::::new(13, false); +// let b = IntegerTrait::::new(42, false); +// let result = a - b; +// assert(result.mag == 29, '13 - 42 = -29'); +// assert(result.sign == true, '13 - 42 -> negative'); + +// // Test subtraction of two negative integers with larger first +// let a = IntegerTrait::::new(42, true); +// let b = IntegerTrait::::new(13, true); +// let result = a - b; +// assert(result.mag == 29, '-42 - -13 = 29'); +// assert(result.sign == true, '-42 - -13 -> negative'); + +// // Test subtraction of two negative integers with larger second +// let a = IntegerTrait::::new(13, true); +// let b = IntegerTrait::::new(42, true); +// let result = a - b; +// assert(result.mag == 29, '-13 - -42 = 29'); +// assert(result.sign == false, '-13 - -42 -> positive'); + +// // Test subtraction of a positive integer and a negative integer with the same magnitude +// let a = IntegerTrait::::new(42, false); +// let b = IntegerTrait::::new(42, true); +// let result = a - b; +// assert(result.mag == 84, '42 - -42 = 84'); +// assert(result.sign == false, '42 - -42 -> postive'); + +// // Test subtraction of a negative integer and a positive integer with the same magnitude +// let a = IntegerTrait::::new(42, true); +// let b = IntegerTrait::::new(42, false); +// let result = a - b; +// assert(result.mag == 84, '-42 - 42 = -84'); +// assert(result.sign == true, '-42 - 42 -> negative'); + +// // Test subtraction of a positive integer and a negative integer with different magnitudes +// let a = IntegerTrait::::new(100, false); +// let b = IntegerTrait::::new(42, true); +// let result = a - b; +// assert(result.mag == 142, '100 - - 42 = 142'); +// assert(result.sign == false, '100 - - 42 -> postive'); + +// // Test subtraction of a negative integer and a positive integer with different magnitudes +// let a = IntegerTrait::::new(42, true); +// let b = IntegerTrait::::new(100, false); +// let result = a - b; +// assert(result.mag == 142, '-42 - 100 = -142'); +// assert(result.sign == true, '-42 - 100 -> negative'); + +// // Test subtraction resulting in zero +// let a = IntegerTrait::::new(42, false); +// let b = IntegerTrait::::new(42, false); +// let result = a - b; +// assert(result.mag == 0, '42 - 42 = 0'); +// assert(result.sign == false, '42 - 42 -> positive'); +// } + +// #[test] +// fn test_mul() { +// // Test multiplication of positive integers +// let a = IntegerTrait::::new(10, false); +// let b = IntegerTrait::::new(5, false); +// let result = a * b; +// assert(result.mag == 50, '10 * 5 = 50'); +// assert(result.sign == false, '10 * 5 -> positive'); + +// // Test multiplication of negative integers +// let a = IntegerTrait::::new(10, true); +// let b = IntegerTrait::::new(5, true); +// let result = a * b; +// assert(result.mag == 50, '-10 * -5 = 50'); +// assert(result.sign == false, '-10 * -5 -> positive'); + +// // Test multiplication of positive and negative integers +// let a = IntegerTrait::::new(10, false); +// let b = IntegerTrait::::new(5, true); +// let result = a * b; +// assert(result.mag == 50, '10 * -5 = -50'); +// assert(result.sign == true, '10 * -5 -> negative'); + +// // Test multiplication by zero +// let a = IntegerTrait::::new(10, false); +// let b = IntegerTrait::::new(0, false); +// let result = a * b; +// assert(result.mag == 0, '10 * 0 = 0'); +// assert(result.sign == false, '10 * 0 -> positive'); +// } + +// #[test] +// fn test_div_no_rem() { +// // Test division of positive integers +// let a = IntegerTrait::::new(10, false); +// let b = IntegerTrait::::new(5, false); +// let result = a / b; +// assert(result.mag == 2, '10 // 5 = 2'); +// assert(result.sign == false, '10 // 5 -> positive'); + +// // Test division of negative integers +// let a = IntegerTrait::::new(10, true); +// let b = IntegerTrait::::new(5, true); +// let result = a / b; +// assert(result.mag == 2, '-10 // -5 = 2'); +// assert(result.sign == false, '-10 // -5 -> positive'); + +// // Test division of positive and negative integers +// let a = IntegerTrait::::new(10, false); +// let b = IntegerTrait::::new(5, true); +// let result = a / b; +// assert(result.mag == 2, '10 // -5 = -2'); +// assert(result.sign == true, '10 // -5 -> negative'); + +// // Test division with a = zero +// let a = IntegerTrait::::new(0, false); +// let b = IntegerTrait::::new(10, false); +// let result = a / b; +// assert(result.mag == 0, '0 // 10 = 0'); +// assert(result.sign == false, '0 // 10 -> positive'); + +// // Test division with a = zero +// let a = IntegerTrait::::new(0, false); +// let b = IntegerTrait::::new(10, false); +// let result = a / b; +// assert(result.mag == 0, '0 // 10 = 0'); +// assert(result.sign == false, '0 // 10 -> positive'); +// } + +// #[test] +// #[available_gas(20000000)] +// fn test_div_rem() { +// // Test division and remainder of positive integers +// let a = IntegerTrait::::new(13, false); +// let b = IntegerTrait::::new(5, false); +// let (q, r) = a.div_rem(b); +// assert(q.mag == 2 && r.mag == 3, '13 // 5 = 2 r 3'); +// assert((q.sign == false) & (r.sign == false), '13 // 5 -> positive'); + +// // Test division and remainder of negative integers +// let a = IntegerTrait::::new(13, true); +// let b = IntegerTrait::::new(5, true); +// let (q, r) = a.div_rem(b); +// assert(q.mag == 2 && r.mag == 3, '-13 // -5 = 2 r -3'); +// assert(q.sign == false && r.sign == true, '-13 // -5 -> positive'); + +// // Test division and remainder of positive and negative integers +// let a = IntegerTrait::::new(13, false); +// let b = IntegerTrait::::new(5, true); +// let (q, r) = a.div_rem(b); +// assert(q.mag == 3 && r.mag == 2, '13 // -5 = -3 r -2'); +// assert(q.sign == true && r.sign == true, '13 // -5 -> negative'); + +// // Test division with a = zero +// let a = IntegerTrait::::new(0, false); +// let b = IntegerTrait::::new(10, false); +// let (q, r) = a.div_rem(b); +// assert(q.mag == 0 && r.mag == 0, '0 // 10 = 0 r 0'); +// assert(q.sign == false && r.sign == false, '0 // 10 -> positive'); + +// // Test division and remainder with a negative dividend and positive divisor +// let a = IntegerTrait::::new(13, true); +// let b = IntegerTrait::::new(5, false); +// let (q, r) = a.div_rem(b); +// assert(q.mag == 3 && r.mag == 2, '-13 // 5 = -3 r 2'); +// assert(q.sign == true && r.sign == false, '-13 // 5 -> negative'); +// } + + diff --git a/src/tests/operators/nn.cairo b/src/tests/operators/nn.cairo index af83870f0..416465a64 100644 --- a/src/tests/operators/nn.cairo +++ b/src/tests/operators/nn.cairo @@ -1 +1 @@ -mod functional; \ No newline at end of file +mod functional; diff --git a/src/tests/operators/tensor.cairo b/src/tests/operators/tensor.cairo index 18677472d..c88f4f133 100644 --- a/src/tests/operators/tensor.cairo +++ b/src/tests/operators/tensor.cairo @@ -1,3 +1,3 @@ mod math; mod linalg; -mod core; \ No newline at end of file +mod core; diff --git a/src/tests/operators/tensor/math.cairo b/src/tests/operators/tensor/math.cairo index 826039c61..ed6f66c49 100644 --- a/src/tests/operators/tensor/math.cairo +++ b/src/tests/operators/tensor/math.cairo @@ -13,3 +13,4 @@ mod abs; mod ceil; mod ln; mod arithmetic; +mod sin; diff --git a/src/tests/operators/tensor/math/sin.cairo b/src/tests/operators/tensor/math/sin.cairo new file mode 100644 index 000000000..d1d7c6adf --- /dev/null +++ b/src/tests/operators/tensor/math/sin.cairo @@ -0,0 +1,4 @@ +mod sin_u32_test; +mod sin_i32_test; +mod sin_fp_test; + diff --git a/src/tests/operators/tensor/math/sin/sin_fp_test.cairo b/src/tests/operators/tensor/math/sin/sin_fp_test.cairo new file mode 100644 index 000000000..94f48855a --- /dev/null +++ b/src/tests/operators/tensor/math/sin/sin_fp_test.cairo @@ -0,0 +1,2 @@ +mod sin_fp8x23_test; +mod sin_fp16x16_test; diff --git a/src/tests/operators/tensor/math/sin/sin_fp_test/sin_fp16x16_test.cairo b/src/tests/operators/tensor/math/sin/sin_fp_test/sin_fp16x16_test.cairo new file mode 100644 index 000000000..1c7aefee4 --- /dev/null +++ b/src/tests/operators/tensor/math/sin/sin_fp_test/sin_fp16x16_test.cairo @@ -0,0 +1,84 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.sin().data; + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 55147, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 59592, 'result[2] = 0.909...'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 55147, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 59592, 'result[2] = 0.909...'); + assert((*result.at(3).mag).into() == 9246, 'result[3] = 0.141...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 55147, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 59592, 'result[2] = 0.909...'); + assert((*result.at(3).mag).into() == 9246, 'result[3] = 0.141...'); + assert((*result.at(4).mag).into() == 49598, 'result[3] = -0.7568...'); + assert((*result.at(4).sign).into() == true, 'result[3].sign = true'); + assert((*result.at(5).mag).into() == 62844, 'result[3] = -0.9589...'); + assert((*result.at(5).sign).into() == true, 'result[3].sign = true'); + assert((*result.at(6).mag).into() == 18310, 'result[3] = -0.2794...'); + assert((*result.at(6).sign).into() == true, 'result[3].sign = true...'); + assert((*result.at(7).mag).into() == 43056, 'result[3] = 0.6569...'); + assert((*result.at(7).sign).into() == false, 'result[3].sign = false'); + } +} diff --git a/src/tests/operators/tensor/math/sin/sin_fp_test/sin_fp8x23_test.cairo b/src/tests/operators/tensor/math/sin/sin_fp_test/sin_fp8x23_test.cairo new file mode 100644 index 000000000..4ae4c9f18 --- /dev/null +++ b/src/tests/operators/tensor/math/sin/sin_fp_test/sin_fp8x23_test.cairo @@ -0,0 +1,84 @@ +use core::clone::Clone; + +// ===== 1D ===== // +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.sin().data; + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 7058771, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 7627740, 'result[2] = 0.9092...'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 7058771, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 7627740, 'result[2] = 0.9092...'); + assert((*result.at(3).mag).into() == 1183800, 'result[3] = 0.1411...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 7058771, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 7627740, 'result[2] = 0.9092...'); + assert((*result.at(3).mag).into() == 1183800, 'result[3] = 0.1411...'); + assert((*result.at(4).mag).into() == 6348520, 'result[3] = -0.7568...'); + assert((*result.at(4).sign).into() == true, 'result[3].sign = true'); + assert((*result.at(5).mag).into() == 8044040, 'result[3] = -0.9589...'); + assert((*result.at(5).sign).into() == true, 'result[3].sign = true'); + assert((*result.at(6).mag).into() == 2343908, 'result[3] = -0.2794...'); + assert((*result.at(6).sign).into() == true, 'result[3].sign = true...'); + assert((*result.at(7).mag).into() == 5511203, 'result[3] = 0.6569...'); + assert((*result.at(7).sign).into() == false, 'result[3].sign = false'); + } +} diff --git a/src/tests/operators/tensor/math/sin/sin_i32_test.cairo b/src/tests/operators/tensor/math/sin/sin_i32_test.cairo new file mode 100644 index 000000000..fd38cb115 --- /dev/null +++ b/src/tests/operators/tensor/math/sin/sin_i32_test.cairo @@ -0,0 +1,84 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = i32_tensor_1x3_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 55147, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 59592, 'result[2] = 0.909...'); + } +} +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = i32_tensor_2x2_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 55147, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 59592, 'result[2] = 0.909...'); + assert((*result.at(3).mag).into() == 9246, 'result[3] = 0.1411...'); + } +} +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::i32::i32_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = i32_tensor_2x2x2_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 55147, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 59592, 'result[2] = 0.909...'); + assert((*result.at(3).mag).into() == 9246, 'result[3] = 0.1411...'); + assert((*result.at(4).mag).into() == 49598, 'result[3] = -0.7568...'); + assert((*result.at(4).sign).into() == true, 'result[3].sign = true'); + assert((*result.at(5).mag).into() == 62844, 'result[3] = -0.9589...'); + assert((*result.at(5).sign).into() == true, 'result[3].sign = true'); + assert((*result.at(6).mag).into() == 18310, 'result[3] = -0.2794...'); + assert((*result.at(6).sign).into() == true, 'result[3].sign = true...'); + assert((*result.at(7).mag).into() == 43056, 'result[3] = 0.6569...'); + assert((*result.at(7).sign).into() == false, 'result[3].sign = false'); + } +} + diff --git a/src/tests/operators/tensor/math/sin/sin_u32_test.cairo b/src/tests/operators/tensor/math/sin/sin_u32_test.cairo new file mode 100644 index 000000000..76fd2368e --- /dev/null +++ b/src/tests/operators/tensor/math/sin/sin_u32_test.cairo @@ -0,0 +1,80 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::u32::u32_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = u32_tensor_1x3_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 55147, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 59592, 'result[2] = 0.909...'); + } +} +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + + #[test] + #[available_gas(20000000)] + fn tensor_sin_test() { + let tensor = u32_tensor_2x2_helper(); + let result = tensor.sin().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 55147, 'result[1] = 0.8414...'); + assert((*result.at(2).mag).into() == 59592, 'result[2] = 0.909...'); + assert((*result.at(3).mag).into() == 9246, 'result[3] = 0.141...'); + } +} +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::u32::u32_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_exp_test() { + let tensor = u32_tensor_2x2x2_helper(); + let result = tensor.exp().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 178142, 'result[1] = 2.7182...'); + assert((*result.at(2).mag).into() == 484232, 'result[2] = 7.389...'); + assert((*result.at(3).mag).into() == 1316288, 'result[3] = 20.085...'); + assert((*result.at(4).mag).into() == 3577984, 'result[3] = 54.5981...'); + assert((*result.at(5).mag).into() == 9726080, 'result[3] = 148.4131...'); + assert((*result.at(6).mag).into() == 26437888, 'result[3] = 403.4287...'); + assert((*result.at(7).mag).into() == 71866368, 'result[3] = 1096.6331...'); + } +} + From f6aeab9a7b9547de239d9b27c2f6f5c0c2688d67 Mon Sep 17 00:00:00 2001 From: Roy Date: Tue, 27 Jun 2023 23:11:08 -0700 Subject: [PATCH 057/126] Added sinh w/ tests --- docs/CHANGELOG.md | 18 ++- docs/apis/compatibility.md | 71 +++++------ docs/apis/numbers/fixed-point/fp.sinh.md | 28 +++++ docs/apis/operators/tensor/tensor.new.md | 2 +- docs/apis/operators/tensor/tensor.sinh.md | 35 ++++++ src/numbers/fixed_point/core.cairo | 30 +++++ .../implementations/impl_16x16.cairo | 4 + .../implementations/impl_8x23.cairo | 4 + src/numbers/fixed_point/math/math_16x16.cairo | 8 ++ src/numbers/fixed_point/math/math_8x23.cairo | 8 ++ src/operators/tensor/core.cairo | 36 ++++++ .../implementations/impl_tensor_fp.cairo | 5 + .../implementations/impl_tensor_i32.cairo | 5 + .../implementations/impl_tensor_u32.cairo | 4 + src/operators/tensor/math.cairo | 1 + src/operators/tensor/math/sinh.cairo | 3 + src/operators/tensor/math/sinh/sinh_fp.cairo | 3 + .../tensor/math/sinh/sinh_fp/core.cairo | 18 +++ .../tensor/math/sinh/sinh_fp/fp16x16.cairo | 28 +++++ .../tensor/math/sinh/sinh_fp/fp8x23.cairo | 28 +++++ src/operators/tensor/math/sinh/sinh_i32.cairo | 3 + .../tensor/math/sinh/sinh_i32/core.cairo | 19 +++ .../tensor/math/sinh/sinh_i32/fp16x16.cairo | 37 ++++++ .../tensor/math/sinh/sinh_i32/fp8x23.cairo | 37 ++++++ src/operators/tensor/math/sinh/sinh_u32.cairo | 3 + .../tensor/math/sinh/sinh_u32/core.cairo | 19 +++ .../tensor/math/sinh/sinh_u32/fp16x16.cairo | 31 +++++ .../tensor/math/sinh/sinh_u32/fp8x23.cairo | 31 +++++ .../numbers/fixed_point/fp16x16_test.cairo | 7 ++ .../numbers/fixed_point/fp8x23_test.cairo | 7 ++ src/tests/operators/tensor/math.cairo | 1 + src/tests/operators/tensor/math/sinh.cairo | 3 + .../tensor/math/sinh/sinh_fp_test.cairo | 2 + .../sinh/sinh_fp_test/sinh_fp16x16_test.cairo | 80 +++++++++++++ .../sinh/sinh_fp_test/sinh_fp8x23_test.cairo | 79 ++++++++++++ .../tensor/math/sinh/sinh_i32_test.cairo | 113 ++++++++++++++++++ .../tensor/math/sinh/sinh_u32_test.cairo | 110 +++++++++++++++++ 37 files changed, 883 insertions(+), 38 deletions(-) create mode 100644 docs/apis/numbers/fixed-point/fp.sinh.md create mode 100644 docs/apis/operators/tensor/tensor.sinh.md create mode 100644 src/operators/tensor/math/sinh.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_fp.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_fp/core.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_fp/fp16x16.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_fp/fp8x23.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_i32.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_i32/core.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_u32.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_u32/core.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_u32/fp16x16.cairo create mode 100644 src/operators/tensor/math/sinh/sinh_u32/fp8x23.cairo create mode 100644 src/tests/operators/tensor/math/sinh.cairo create mode 100644 src/tests/operators/tensor/math/sinh/sinh_fp_test.cairo create mode 100644 src/tests/operators/tensor/math/sinh/sinh_fp_test/sinh_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/math/sinh/sinh_fp_test/sinh_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/math/sinh/sinh_i32_test.cairo create mode 100644 src/tests/operators/tensor/math/sinh/sinh_u32_test.cairo diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e21d1ee07..404f8de0d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,40 +4,53 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] - 2023-06-27 + +### Added + +- Added sinh operator + ## [Unreleased] - 2023-06-24 ### Added + - Added cumsum operator ## [Unreleased] - 2023-06-23 ### Changed + - Replace array.at with IndexView ## [Unreleased] - 2023-06-21 ### Changed + - Refactor nn tests to cover n-dimensions ## [Unreleased] - 2023-06-21 ### Changed + - Refactor tensor tests to cover n-dimensions ## [Unreleased] - 2023-06-20 ### Changed + - Upgrade Cairo version to v2.0.0-rc ## [Unreleased] - 2023-06-17 ### Added + - Into trait to signed integers ## [Unreleased] - 2023-06-16 ### Changed -- Updated argmax function parameters + +- Updated argmax function parameters - Restructured tests for argmax and argmin ## [Unreleased] - 2023-06-11 @@ -46,10 +59,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Added ln functionality to tensor trait. Added Logsoftmax implementation for nn trait. - Added tests for both. - + ## [Unreleased] - 2023-06-08 ### Added + - Added argmin tensor operator ## [Unreleased] - 2023-06-07 diff --git a/docs/apis/compatibility.md b/docs/apis/compatibility.md index 96e99a305..93219de55 100644 --- a/docs/apis/compatibility.md +++ b/docs/apis/compatibility.md @@ -4,42 +4,43 @@ To see the full list of available ONNX Operators refer to [this table](https://g You can see below the list of current supported ONNX Operators: -| Operator | Implemented | -| :---------------------------------------------------------: | :------------------: | -| [MatMul](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | -| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | -| [Add](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Sub](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Mul](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Div](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Equal](operators/tensor/tensor.eq.md) | :white\_check\_mark: | -| [Greater](operators/tensor/tensor.greater.md) | :white\_check\_mark: | -| [GreaterOrEqual](operators/tensor/tensor.greater\_equal.md) | :white\_check\_mark: | -| [Less](operators/tensor/tensor.less.md) | :white\_check\_mark: | -| [LessOrEqual](operators/tensor/tensor.less\_equal.md) | :white\_check\_mark: | -| [Abs](operators/tensor/tensor.abs.md) | :white\_check\_mark: | -| [Ceil](operators/tensor/tensor.ceil.md) | :white\_check\_mark: | -| [Exp](operators/tensor/tensor.exp.md) | :white\_check\_mark: | -| [Ln](operators/tensor/tensor.ln.md) | :white\_check\_mark: | -| [Reshape](operators/tensor/tensor.reshape.md) | :white\_check\_mark: | -| [Transpose](operators/tensor/tensor.transpose.md) | :white\_check\_mark: | -| [ArgMax](operators/tensor/tensor.argmax.md) | :white\_check\_mark: | -| [ArgMin](operators/tensor/tensor.argmin.md) | :white\_check\_mark: | -| [ReduceSum](operators/tensor/tensor.reduce\_sum.md) | :white\_check\_mark: | -| [CumSum](operators/tensor/tensor.cumsum.md) | :white\_check\_mark: | -| [Relu](operators/neural-network/nn.relu.md) | :white\_check\_mark: | -| [LeakyRelu](operators/neural-network/nn.leaky\_relu.md) | :white\_check\_mark: | -| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white\_check\_mark: | -| [Softmax](operators/neural-network/nn.softmax.md) | :white\_check\_mark: | -| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white\_check\_mark: | -| [Softsign](operators/neural-network/nn.softsign.md) | :white\_check\_mark: | -| [Softplus](operators/neural-network/nn.softplus.md) | :white\_check\_mark: | -| [Linear](operators/neural-network/nn.linear.md) | :white\_check\_mark: | +| Operator | Implemented | +| :--------------------------------------------------------: | :----------------: | +| [MatMul](operators/tensor/tensor.matmul.md) | :white_check_mark: | +| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white_check_mark: | +| [Add](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Sub](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Mul](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Div](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Equal](operators/tensor/tensor.eq.md) | :white_check_mark: | +| [Greater](operators/tensor/tensor.greater.md) | :white_check_mark: | +| [GreaterOrEqual](operators/tensor/tensor.greater_equal.md) | :white_check_mark: | +| [Less](operators/tensor/tensor.less.md) | :white_check_mark: | +| [LessOrEqual](operators/tensor/tensor.less_equal.md) | :white_check_mark: | +| [Abs](operators/tensor/tensor.abs.md) | :white_check_mark: | +| [Ceil](operators/tensor/tensor.ceil.md) | :white_check_mark: | +| [Exp](operators/tensor/tensor.exp.md) | :white_check_mark: | +| [Ln](operators/tensor/tensor.ln.md) | :white_check_mark: | +| [Reshape](operators/tensor/tensor.reshape.md) | :white_check_mark: | +| [Transpose](operators/tensor/tensor.transpose.md) | :white_check_mark: | +| [ArgMax](operators/tensor/tensor.argmax.md) | :white_check_mark: | +| [ArgMin](operators/tensor/tensor.argmin.md) | :white_check_mark: | +| [ReduceSum](operators/tensor/tensor.reduce_sum.md) | :white_check_mark: | +| [CumSum](operators/tensor/tensor.cumsum.md) | :white_check_mark: | +| [Relu](operators/neural-network/nn.relu.md) | :white_check_mark: | +| [LeakyRelu](operators/neural-network/nn.leaky_relu.md) | :white_check_mark: | +| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white_check_mark: | +| [Softmax](operators/neural-network/nn.softmax.md) | :white_check_mark: | +| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white_check_mark: | +| [Softsign](operators/neural-network/nn.softsign.md) | :white_check_mark: | +| [Softplus](operators/neural-network/nn.softplus.md) | :white_check_mark: | +| [Linear](operators/neural-network/nn.linear.md) | :white_check_mark: | +| [Sinh](operators/tensor/tensor.sinh.md) | :white_check_mark: | Performance optimizations: -| Optimization | Implemented | -| :----------------: | :------------------: | -| 8-bit quantization | :white\_check\_mark: | +| Optimization | Implemented | +| :----------------: | :----------------: | +| 8-bit quantization | :white_check_mark: | -Current Operators support: **27/156 (17%)** +Current Operators support: **28/156 (18%)** diff --git a/docs/apis/numbers/fixed-point/fp.sinh.md b/docs/apis/numbers/fixed-point/fp.sinh.md new file mode 100644 index 000000000..2437bdd10 --- /dev/null +++ b/docs/apis/numbers/fixed-point/fp.sinh.md @@ -0,0 +1,28 @@ +# fp.sinh + +```rust +fn sinh(self: FixedType) -> FixedType; +``` + +Returns the value of the hyperbolic sine of the fixed point number. + +## Args + +- `self`(`FixedType`) - The input fixed point + +## Returns + +The hyperbolic sine of the input fixed point number. + +## Examples + +```rust +fn sinh_fp_example() -> FixedType { +// We instantiate fixed point here. +let fp = FixedTrait::from_unscaled_felt(2); + +// We can call `sinh` function as follows. +fp.sinh() +} +>>> {mag: 30424303, sign: false} // = 3.6268604 +``` diff --git a/docs/apis/operators/tensor/tensor.new.md b/docs/apis/operators/tensor/tensor.new.md index 46175508e..dc7955a2c 100644 --- a/docs/apis/operators/tensor/tensor.new.md +++ b/docs/apis/operators/tensor/tensor.new.md @@ -84,4 +84,4 @@ let tensor = TensorTrait::::new(shape.span(), data.span(), extra); return tensor; } -``` \ No newline at end of file +``` diff --git a/docs/apis/operators/tensor/tensor.sinh.md b/docs/apis/operators/tensor/tensor.sinh.md new file mode 100644 index 000000000..575472f97 --- /dev/null +++ b/docs/apis/operators/tensor/tensor.sinh.md @@ -0,0 +1,35 @@ +# tensor.sinh + +```rust +fn sinh(self: @Tensor) -> Tensor; +``` + +Computes the exponential of all elements of the input tensor. + +$$ +y_i=sinh({x_i}) +$$ + +## Args + +- `self`(`@Tensor`) - The input tensor. + +## Returns + +Returns a new tensor in `FixedType` with the exponential of the elements of the input tensor. + +## Examples + +```rust +fn exp_example() -> Tensor { +// We instantiate a 2D Tensor here. +// [[0,1],[2,3]] +let tensor = u32_tensor_2x2_helper(); + +// We can call `sinh` function as follows. +return tensor.sinh(); +} +>>> [[0,9858303],[30424303,84036026]] +// The fixed point representation of +// [[0, 1.175201],[3.62686, 10.0178749]] +``` diff --git a/src/numbers/fixed_point/core.cairo b/src/numbers/fixed_point/core.cairo index 58d939f18..0fd88c80b 100644 --- a/src/numbers/fixed_point/core.cairo +++ b/src/numbers/fixed_point/core.cairo @@ -481,4 +481,34 @@ trait FixedTrait { /// ``` /// fn sqrt(self: FixedType) -> FixedType; + /// # fp.sinh + /// + /// ```rust + /// fn sinh(self: FixedType) -> FixedType; + /// ``` + /// + /// Returns the value of the hyperbolic sine of the fixed point number. + /// + /// ## Args + /// + /// * `self`(`FixedType`) - The input fixed point + /// + /// ## Returns + /// + /// The hyperbolic sine of the input fixed point number. + /// + /// ## Examples + /// + /// ```rust + /// fn sinh_fp_example() -> FixedType { + /// // We instantiate fixed point here. + /// let fp = FixedTrait::from_unscaled_felt(2); + /// + /// // We can call `sinh` function as follows. + /// fp.sinh() + /// } + /// >>> {mag: 30424311, sign: false} // = 3.6268604 + /// ``` + /// + fn sinh(self: FixedType) -> FixedType; } diff --git a/src/numbers/fixed_point/implementations/impl_16x16.cairo b/src/numbers/fixed_point/implementations/impl_16x16.cairo index 943df4761..d5d6efaca 100644 --- a/src/numbers/fixed_point/implementations/impl_16x16.cairo +++ b/src/numbers/fixed_point/implementations/impl_16x16.cairo @@ -81,6 +81,10 @@ impl FP16x16Impl of FixedTrait { fn sqrt(self: FixedType) -> FixedType { return math_16x16::sqrt(self); } + + fn sinh(self: FixedType) -> FixedType { + return math_16x16::sinh(self); + } } impl FP16x16Print of PrintTrait { diff --git a/src/numbers/fixed_point/implementations/impl_8x23.cairo b/src/numbers/fixed_point/implementations/impl_8x23.cairo index 97428ddf3..16869e291 100644 --- a/src/numbers/fixed_point/implementations/impl_8x23.cairo +++ b/src/numbers/fixed_point/implementations/impl_8x23.cairo @@ -81,6 +81,10 @@ impl FP8x23Impl of FixedTrait { fn sqrt(self: FixedType) -> FixedType { return math_8x23::sqrt(self); } + + fn sinh(self: FixedType) -> FixedType { + return math_8x23::sinh(self); + } } impl FP8x23Print of PrintTrait { diff --git a/src/numbers/fixed_point/math/math_16x16.cairo b/src/numbers/fixed_point/math/math_16x16.cairo index 9b8354928..bd8ee85d6 100644 --- a/src/numbers/fixed_point/math/math_16x16.cairo +++ b/src/numbers/fixed_point/math/math_16x16.cairo @@ -453,3 +453,11 @@ fn _pow_int(a: FixedType, b: u128, sign: bool) -> FixedType { fn _split_unsigned(a: FixedType) -> (u128, u128) { return integer::u128_safe_divmod(a.mag, integer::u128_as_non_zero(ONE)); } + +/// Cf: FixedTrait::sinh docstring +fn sinh(a: FixedType) -> FixedType { + let ea = a.exp(); + let num = ea - (FixedTrait::new(ONE, false) / ea); + let denom = FixedTrait::new_unscaled(2_u128, false); + num / denom +} diff --git a/src/numbers/fixed_point/math/math_8x23.cairo b/src/numbers/fixed_point/math/math_8x23.cairo index 658d0c86b..8a4616840 100644 --- a/src/numbers/fixed_point/math/math_8x23.cairo +++ b/src/numbers/fixed_point/math/math_8x23.cairo @@ -455,3 +455,11 @@ fn _pow_int(a: FixedType, b: u128, sign: bool) -> FixedType { fn _split_unsigned(a: FixedType) -> (u128, u128) { return integer::u128_safe_divmod(a.mag, integer::u128_as_non_zero(ONE)); } + +/// Cf: FixedTrait::sinh docstring +fn sinh(a: FixedType) -> FixedType { + let ea = a.exp(); + let num = ea - (FixedTrait::new(ONE, false) / ea); + let denom = FixedTrait::new_unscaled(2_u128, false); + num / denom +} diff --git a/src/operators/tensor/core.cairo b/src/operators/tensor/core.cairo index 434160fce..5bbd25a3a 100644 --- a/src/operators/tensor/core.cairo +++ b/src/operators/tensor/core.cairo @@ -1185,6 +1185,42 @@ trait TensorTrait { /// ``` /// fn cumsum(self: @Tensor, axis: usize, exclusive: Option, reverse: Option) -> Tensor; + /// # tensor.sinh + /// + /// ```rust + /// fn sinh(self: @Tensor) -> Tensor; + /// ``` + /// + /// Computes the exponential of all elements of the input tensor. + /// $$ + /// y_i=sinh({x_i}) + /// $$ + /// + /// ## Args + /// + /// * `self`(`@Tensor`) - The input tensor. + /// + /// ## Returns + /// + /// Returns a new tensor in `FixedType` with the exponential of the elements of the input tensor. + /// + /// ## Examples + /// + /// ```rust + /// fn exp_example() -> Tensor { + /// // We instantiate a 2D Tensor here. + /// // [[0,1],[2,3]] + /// let tensor = u32_tensor_2x2_helper(); + /// + /// // We can call `sinh` function as follows. + /// return tensor.sinh(); + /// } + /// >>> [[0,9858303],[30424311,84036026]] + /// // The fixed point representation of + /// // [[0, 1.175201],[3.62686, 10.0178749]] + /// ``` + /// + fn sinh(self: @Tensor) -> Tensor; } /// Cf: TensorTrait::new docstring diff --git a/src/operators/tensor/implementations/impl_tensor_fp.cairo b/src/operators/tensor/implementations/impl_tensor_fp.cairo index 8e3666302..07bc4bcb2 100644 --- a/src/operators/tensor/implementations/impl_tensor_fp.cairo +++ b/src/operators/tensor/implementations/impl_tensor_fp.cairo @@ -28,6 +28,7 @@ use orion::operators::tensor::math::arithmetic::arithmetic_fp::core::{add, sub, use orion::operators::tensor::math::greater::greater_fp::core::greater; use orion::operators::tensor::math::greater_equal::greater_equal_fp::core::greater_equal; use orion::operators::tensor::math::cumsum::cumsum_fp::core::cumsum; +use orion::operators::tensor::math::sinh::sinh_fp::core::sinh; use orion::utils::check_gas; @@ -125,6 +126,10 @@ impl Tensor_fp of TensorTrait { fn cumsum(self: @Tensor, axis: usize, exclusive:Option, reverse:Option) -> Tensor { cumsum(self, axis, exclusive, reverse).unwrap() } + + fn sinh(self: @Tensor) -> Tensor { + sinh(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_i32.cairo b/src/operators/tensor/implementations/impl_tensor_i32.cairo index 586b81060..feee98048 100644 --- a/src/operators/tensor/implementations/impl_tensor_i32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_i32.cairo @@ -29,6 +29,7 @@ use orion::operators::tensor::math::exp::exp_i32::core::exp_i32; use orion::operators::tensor::math::ln::ln_i32::core::ln_i32; use orion::operators::tensor::math::arithmetic::arithmetic_i32::{add, sub, mul, div}; use orion::operators::tensor::math::cumsum::cumsum_i32::cumsum; +use orion::operators::tensor::math::sinh::sinh_i32::core::sinh_i32; use orion::utils::check_gas; impl Tensor_i32 of TensorTrait { @@ -123,6 +124,10 @@ impl Tensor_i32 of TensorTrait { fn cumsum(self: @Tensor, axis: usize, exclusive:Option, reverse:Option) -> Tensor { cumsum(self, axis, exclusive, reverse) } + + fn sinh(self: @Tensor) -> Tensor { + sinh_i32(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_u32.cairo b/src/operators/tensor/implementations/impl_tensor_u32.cairo index 4cf84524a..b397d9637 100644 --- a/src/operators/tensor/implementations/impl_tensor_u32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_u32.cairo @@ -28,6 +28,7 @@ use orion::operators::tensor::math::exp::exp_u32::core::exp_u32; use orion::operators::tensor::math::ln::ln_u32::core::ln_u32; use orion::operators::tensor::math::arithmetic::arithmetic_u32::{add, sub, mul, div}; use orion::operators::tensor::math::cumsum::cumsum_u32::cumsum; +use orion::operators::tensor::math::sinh::sinh_u32::core::sinh_u32; use orion::utils::check_gas; impl Tensor_u32 of TensorTrait { @@ -123,6 +124,9 @@ impl Tensor_u32 of TensorTrait { fn cumsum(self: @Tensor, axis: usize, exclusive:Option, reverse:Option) -> Tensor { cumsum(self, axis, exclusive, reverse) } + fn sinh(self: @Tensor) -> Tensor { + sinh_u32(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/math.cairo b/src/operators/tensor/math.cairo index f21ba3d67..1cd55664f 100644 --- a/src/operators/tensor/math.cairo +++ b/src/operators/tensor/math.cairo @@ -14,3 +14,4 @@ mod less_equal; mod abs; mod ceil; mod cumsum; +mod sinh; diff --git a/src/operators/tensor/math/sinh.cairo b/src/operators/tensor/math/sinh.cairo new file mode 100644 index 000000000..f4f28f872 --- /dev/null +++ b/src/operators/tensor/math/sinh.cairo @@ -0,0 +1,3 @@ +mod sinh_i32; +mod sinh_u32; +mod sinh_fp; diff --git a/src/operators/tensor/math/sinh/sinh_fp.cairo b/src/operators/tensor/math/sinh/sinh_fp.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_fp.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/sinh/sinh_fp/core.cairo b/src/operators/tensor/math/sinh/sinh_fp/core.cairo new file mode 100644 index 000000000..12258f1a7 --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_fp/core.cairo @@ -0,0 +1,18 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::operators::tensor::math::sinh::sinh_fp::fp8x23; +use orion::operators::tensor::math::sinh::sinh_fp::fp16x16; + +/// Cf: TensorTrait::sinh docstring +fn sinh(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::sinh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::sinh(self)), + }, + Option::None(_) => Option::Some(fp16x16::sinh(self)), + }, + Option::None(_) => Option::Some(fp16x16::sinh(self)), + } +} diff --git a/src/operators/tensor/math/sinh/sinh_fp/fp16x16.cairo b/src/operators/tensor/math/sinh/sinh_fp/fp16x16.cairo new file mode 100644 index 000000000..38f146645 --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_fp/fp16x16.cairo @@ -0,0 +1,28 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::sinh docstring +fn sinh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + result.append(FixedTrait::sinh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sinh/sinh_fp/fp8x23.cairo b/src/operators/tensor/math/sinh/sinh_fp/fp8x23.cairo new file mode 100644 index 000000000..79bee213a --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_fp/fp8x23.cairo @@ -0,0 +1,28 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::sinh docstring +fn sinh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + result.append(FixedTrait::sinh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sinh/sinh_i32.cairo b/src/operators/tensor/math/sinh/sinh_i32.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_i32.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/sinh/sinh_i32/core.cairo b/src/operators/tensor/math/sinh/sinh_i32/core.cairo new file mode 100644 index 000000000..c07afdb59 --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_i32/core.cairo @@ -0,0 +1,19 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::math::sinh::sinh_i32::fp8x23; +use orion::operators::tensor::math::sinh::sinh_i32::fp16x16; + +/// Cf: TensorTrait::sinh docstring +fn sinh_i32(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::sinh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::sinh(self)), + }, + Option::None(_) => Option::Some(fp16x16::sinh(self)), + }, + Option::None(_) => Option::Some(fp16x16::sinh(self)), + } +} diff --git a/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo b/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo new file mode 100644 index 000000000..342132661 --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo @@ -0,0 +1,37 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::sinh docstring +fn sinh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + + if ele.sign == true { + let ele = FixedTrait::from_unscaled_felt((ele.mag).into() * -1); + result.append(FixedTrait::sinh(ele)) + } else { + let ele = FixedTrait::from_unscaled_felt((ele.mag).into()); + result.append(FixedTrait::sinh(ele)) + } + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo b/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo new file mode 100644 index 000000000..f9d7d9c42 --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo @@ -0,0 +1,37 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::sinh docstring +fn sinh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + + if ele.sign == true { + let ele = FixedTrait::from_unscaled_felt((ele.mag).into() * -1); + result.append(FixedTrait::sinh(ele)) + } else { + let ele = FixedTrait::from_unscaled_felt((ele.mag).into()); + result.append(FixedTrait::sinh(ele)) + } + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sinh/sinh_u32.cairo b/src/operators/tensor/math/sinh/sinh_u32.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_u32.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/sinh/sinh_u32/core.cairo b/src/operators/tensor/math/sinh/sinh_u32/core.cairo new file mode 100644 index 000000000..27fffa843 --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_u32/core.cairo @@ -0,0 +1,19 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::math::sinh::sinh_u32::fp8x23; +use orion::operators::tensor::math::sinh::sinh_u32::fp16x16; + +/// Cf: TensorTrait::sinh docstring +fn sinh_u32(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::sinh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::sinh(self)), + }, + Option::None(_) => Option::Some(fp16x16::sinh(self)), + }, + Option::None(_) => Option::Some(fp16x16::sinh(self)), + } +} diff --git a/src/operators/tensor/math/sinh/sinh_u32/fp16x16.cairo b/src/operators/tensor/math/sinh/sinh_u32/fp16x16.cairo new file mode 100644 index 000000000..4d7f40e85 --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_u32/fp16x16.cairo @@ -0,0 +1,31 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::sinh docstring +fn sinh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = FixedTrait::from_unscaled_felt((*data.pop_front().unwrap()).into()); + + result.append(FixedTrait::sinh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/sinh/sinh_u32/fp8x23.cairo b/src/operators/tensor/math/sinh/sinh_u32/fp8x23.cairo new file mode 100644 index 000000000..fbe6c6583 --- /dev/null +++ b/src/operators/tensor/math/sinh/sinh_u32/fp8x23.cairo @@ -0,0 +1,31 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::sinh docstring +fn sinh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = FixedTrait::from_unscaled_felt((*data.pop_front().unwrap()).into()); + + result.append(FixedTrait::sinh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/tests/numbers/fixed_point/fp16x16_test.cairo b/src/tests/numbers/fixed_point/fp16x16_test.cairo index ec1233693..1bfcd3d46 100644 --- a/src/tests/numbers/fixed_point/fp16x16_test.cairo +++ b/src/tests/numbers/fixed_point/fp16x16_test.cairo @@ -323,3 +323,10 @@ fn test_gt() { assert(c > b == false, 'c > b'); assert(c > c == false, 'c > c'); } + +#[test] +#[available_gas(10000000)] +fn test_sinh() { + let a = FixedTrait::from_unscaled_felt(1); + assert(a.sinh().into() == 77016, 'invalid sinh of 1'); +} diff --git a/src/tests/numbers/fixed_point/fp8x23_test.cairo b/src/tests/numbers/fixed_point/fp8x23_test.cairo index a7d60c7c6..bfd26c81a 100644 --- a/src/tests/numbers/fixed_point/fp8x23_test.cairo +++ b/src/tests/numbers/fixed_point/fp8x23_test.cairo @@ -323,3 +323,10 @@ fn test_gt() { assert(c > b == false, 'c > b'); assert(c > c == false, 'c > c'); } + +#[test] +#[available_gas(10000000)] +fn test_sinh() { + let a = FixedTrait::from_unscaled_felt(1); + assert(a.sinh().into() == 9858301, 'invalid sinh of 1'); +} \ No newline at end of file diff --git a/src/tests/operators/tensor/math.cairo b/src/tests/operators/tensor/math.cairo index 994687538..74a629cde 100644 --- a/src/tests/operators/tensor/math.cairo +++ b/src/tests/operators/tensor/math.cairo @@ -14,3 +14,4 @@ mod ceil; mod ln; mod arithmetic; mod cumsum; +mod sinh; diff --git a/src/tests/operators/tensor/math/sinh.cairo b/src/tests/operators/tensor/math/sinh.cairo new file mode 100644 index 000000000..0d4088763 --- /dev/null +++ b/src/tests/operators/tensor/math/sinh.cairo @@ -0,0 +1,3 @@ +mod sinh_u32_test; +mod sinh_i32_test; +mod sinh_fp_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/math/sinh/sinh_fp_test.cairo b/src/tests/operators/tensor/math/sinh/sinh_fp_test.cairo new file mode 100644 index 000000000..2cf901a09 --- /dev/null +++ b/src/tests/operators/tensor/math/sinh/sinh_fp_test.cairo @@ -0,0 +1,2 @@ +mod sinh_fp8x23_test; +mod sinh_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/math/sinh/sinh_fp_test/sinh_fp16x16_test.cairo b/src/tests/operators/tensor/math/sinh/sinh_fp_test/sinh_fp16x16_test.cairo new file mode 100644 index 000000000..e6afc688c --- /dev/null +++ b/src/tests/operators/tensor/math/sinh/sinh_fp_test/sinh_fp16x16_test.cairo @@ -0,0 +1,80 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 656513, 'result[3] = 10.0179...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 656513, 'result[3] = 10.0179...'); + assert((*result.at(4).mag).into() == 1788392, 'result[4] = 27.2899...'); + assert((*result.at(5).mag).into() == 4862819, 'result[5] = 74.2032...'); + assert((*result.at(6).mag).into() == 13218863, 'result[6] = 201.7132...'); + assert((*result.at(7).mag).into() == 35933154, 'result[7] = 548.3161...'); + } +} + diff --git a/src/tests/operators/tensor/math/sinh/sinh_fp_test/sinh_fp8x23_test.cairo b/src/tests/operators/tensor/math/sinh/sinh_fp_test/sinh_fp8x23_test.cairo new file mode 100644 index 000000000..ed35d53aa --- /dev/null +++ b/src/tests/operators/tensor/math/sinh/sinh_fp_test/sinh_fp8x23_test.cairo @@ -0,0 +1,79 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 9858301, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 30424303, 'result[2] = 3.62686...'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 9858301, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 30424303, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 84036018, 'result[3] = 10.0179...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 9858301, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 30424303, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 84036018, 'result[3] = 10.0179...'); + assert((*result.at(4).mag).into() == 228924379, 'result[4] = 27.2899...'); + assert((*result.at(5).mag).into() == 622461531, 'result[5] = 74.2032...'); + assert((*result.at(6).mag).into() == 1692092259, 'result[6] = 201.7132...'); + assert((*result.at(7).mag).into() == 4599608079, 'result[7] = 548.3161...'); + } +} + diff --git a/src/tests/operators/tensor/math/sinh/sinh_i32_test.cairo b/src/tests/operators/tensor/math/sinh/sinh_i32_test.cairo new file mode 100644 index 000000000..09e5f868d --- /dev/null +++ b/src/tests/operators/tensor/math/sinh/sinh_i32_test.cairo @@ -0,0 +1,113 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 656513, 'result[3] = 10.0179...'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 656513, 'result[3] = 10.0179...'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(4, false)); + data.append(IntegerTrait::new(5, false)); + data.append(IntegerTrait::new(6, false)); + data.append(IntegerTrait::new(7, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 656513, 'result[3] = 10.0179...'); + assert((*result.at(4).mag).into() == 1788392, 'result[4] = 27.2899...'); + assert((*result.at(5).mag).into() == 4862819, 'result[5] = 74.2032...'); + assert((*result.at(6).mag).into() == 13218863, 'result[6] = 201.7132...'); + assert((*result.at(7).mag).into() == 35933154, 'result[7] = 548.3161...'); + } +} + diff --git a/src/tests/operators/tensor/math/sinh/sinh_u32_test.cairo b/src/tests/operators/tensor/math/sinh/sinh_u32_test.cairo new file mode 100644 index 000000000..c1d37ff71 --- /dev/null +++ b/src/tests/operators/tensor/math/sinh/sinh_u32_test.cairo @@ -0,0 +1,110 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 656513, 'result[3] = 10.0179...'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 656513, 'result[3] = 10.0179...'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_sinh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + data.append(4); + data.append(5); + data.append(6); + data.append(7); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.sinh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 77016, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 237681, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 656513, 'result[3] = 10.0179...'); + assert((*result.at(4).mag).into() == 1788392, 'result[4] = 27.2899...'); + assert((*result.at(5).mag).into() == 4862819, 'result[5] = 74.2032...'); + assert((*result.at(6).mag).into() == 13218863, 'result[6] = 201.7132...'); + assert((*result.at(7).mag).into() == 35933154, 'result[7] = 548.3161...'); + } +} + From ccbba67017586c9e9571d0b5f974002928e167aa Mon Sep 17 00:00:00 2001 From: Roy Rotstein <112157037+Roee-87@users.noreply.github.com> Date: Tue, 27 Jun 2023 23:45:15 -0700 Subject: [PATCH 058/126] Update src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo Co-authored-by: raphaelDkhn <113879115+raphaelDkhn@users.noreply.github.com> --- src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo b/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo index 342132661..51034a6b1 100644 --- a/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo +++ b/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo @@ -21,7 +21,7 @@ fn sinh(self: @Tensor) -> Tensor { let ele = *data.pop_front().unwrap(); if ele.sign == true { - let ele = FixedTrait::from_unscaled_felt((ele.mag).into() * -1); + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); result.append(FixedTrait::sinh(ele)) } else { let ele = FixedTrait::from_unscaled_felt((ele.mag).into()); From 6c43a1f085ac51d6494e95c9a4a379368ebcf5cc Mon Sep 17 00:00:00 2001 From: Roy Rotstein <112157037+Roee-87@users.noreply.github.com> Date: Tue, 27 Jun 2023 23:45:42 -0700 Subject: [PATCH 059/126] Update src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo Co-authored-by: raphaelDkhn <113879115+raphaelDkhn@users.noreply.github.com> --- src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo b/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo index 51034a6b1..fa046f157 100644 --- a/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo +++ b/src/operators/tensor/math/sinh/sinh_i32/fp16x16.cairo @@ -24,7 +24,7 @@ fn sinh(self: @Tensor) -> Tensor { let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); result.append(FixedTrait::sinh(ele)) } else { - let ele = FixedTrait::from_unscaled_felt((ele.mag).into()); + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); result.append(FixedTrait::sinh(ele)) } From 57e13508965b01461154a43a58f2f207ef818c1b Mon Sep 17 00:00:00 2001 From: Roy Rotstein <112157037+Roee-87@users.noreply.github.com> Date: Tue, 27 Jun 2023 23:45:53 -0700 Subject: [PATCH 060/126] Update src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo Co-authored-by: raphaelDkhn <113879115+raphaelDkhn@users.noreply.github.com> --- src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo b/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo index f9d7d9c42..2ae18585a 100644 --- a/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo +++ b/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo @@ -21,7 +21,7 @@ fn sinh(self: @Tensor) -> Tensor { let ele = *data.pop_front().unwrap(); if ele.sign == true { - let ele = FixedTrait::from_unscaled_felt((ele.mag).into() * -1); + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); result.append(FixedTrait::sinh(ele)) } else { let ele = FixedTrait::from_unscaled_felt((ele.mag).into()); From d6d0a12e631fad3ae539c7131f941941ebc42e6b Mon Sep 17 00:00:00 2001 From: Roy Rotstein <112157037+Roee-87@users.noreply.github.com> Date: Tue, 27 Jun 2023 23:46:22 -0700 Subject: [PATCH 061/126] Update src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo Co-authored-by: raphaelDkhn <113879115+raphaelDkhn@users.noreply.github.com> --- src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo b/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo index 2ae18585a..7cb35bbea 100644 --- a/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo +++ b/src/operators/tensor/math/sinh/sinh_i32/fp8x23.cairo @@ -24,7 +24,7 @@ fn sinh(self: @Tensor) -> Tensor { let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); result.append(FixedTrait::sinh(ele)) } else { - let ele = FixedTrait::from_unscaled_felt((ele.mag).into()); + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); result.append(FixedTrait::sinh(ele)) } From 93a611d102926befc08432582a81cd632699d5de Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Wed, 28 Jun 2023 10:36:22 +0300 Subject: [PATCH 062/126] update doc --- docs/SUMMARY.md | 1 + docs/apis/compatibility.md | 73 +++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index ef5095919..fa72c8f5f 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -34,6 +34,7 @@ * [tensor.abs](apis/operators/tensor/tensor.abs.md) * [tensor.ceil](apis/operators/tensor/tensor.ceil.md) * [tensor.cumsum](apis/operators/tensor/tensor.cumsum.md) + * [tensor.sinh](apis/operators/tensor/tensor.sinh.md) * [Neural Network](apis/operators/neural-network/README.md) * [nn.relu](apis/operators/neural-network/nn.relu.md) * [nn.leaky\_relu](apis/operators/neural-network/nn.leaky\_relu.md) diff --git a/docs/apis/compatibility.md b/docs/apis/compatibility.md index 93219de55..f10368f7f 100644 --- a/docs/apis/compatibility.md +++ b/docs/apis/compatibility.md @@ -4,43 +4,44 @@ To see the full list of available ONNX Operators refer to [this table](https://g You can see below the list of current supported ONNX Operators: -| Operator | Implemented | -| :--------------------------------------------------------: | :----------------: | -| [MatMul](operators/tensor/tensor.matmul.md) | :white_check_mark: | -| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white_check_mark: | -| [Add](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Sub](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Mul](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Div](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Equal](operators/tensor/tensor.eq.md) | :white_check_mark: | -| [Greater](operators/tensor/tensor.greater.md) | :white_check_mark: | -| [GreaterOrEqual](operators/tensor/tensor.greater_equal.md) | :white_check_mark: | -| [Less](operators/tensor/tensor.less.md) | :white_check_mark: | -| [LessOrEqual](operators/tensor/tensor.less_equal.md) | :white_check_mark: | -| [Abs](operators/tensor/tensor.abs.md) | :white_check_mark: | -| [Ceil](operators/tensor/tensor.ceil.md) | :white_check_mark: | -| [Exp](operators/tensor/tensor.exp.md) | :white_check_mark: | -| [Ln](operators/tensor/tensor.ln.md) | :white_check_mark: | -| [Reshape](operators/tensor/tensor.reshape.md) | :white_check_mark: | -| [Transpose](operators/tensor/tensor.transpose.md) | :white_check_mark: | -| [ArgMax](operators/tensor/tensor.argmax.md) | :white_check_mark: | -| [ArgMin](operators/tensor/tensor.argmin.md) | :white_check_mark: | -| [ReduceSum](operators/tensor/tensor.reduce_sum.md) | :white_check_mark: | -| [CumSum](operators/tensor/tensor.cumsum.md) | :white_check_mark: | -| [Relu](operators/neural-network/nn.relu.md) | :white_check_mark: | -| [LeakyRelu](operators/neural-network/nn.leaky_relu.md) | :white_check_mark: | -| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white_check_mark: | -| [Softmax](operators/neural-network/nn.softmax.md) | :white_check_mark: | -| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white_check_mark: | -| [Softsign](operators/neural-network/nn.softsign.md) | :white_check_mark: | -| [Softplus](operators/neural-network/nn.softplus.md) | :white_check_mark: | -| [Linear](operators/neural-network/nn.linear.md) | :white_check_mark: | -| [Sinh](operators/tensor/tensor.sinh.md) | :white_check_mark: | +| Operator | Implemented | +| :---------------------------------------------------------: | :------------------: | +| [MatMul](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | +| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | +| [Add](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Sub](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Mul](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Div](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Equal](operators/tensor/tensor.eq.md) | :white\_check\_mark: | +| [Greater](operators/tensor/tensor.greater.md) | :white\_check\_mark: | +| [GreaterOrEqual](operators/tensor/tensor.greater\_equal.md) | :white\_check\_mark: | +| [Less](operators/tensor/tensor.less.md) | :white\_check\_mark: | +| [LessOrEqual](operators/tensor/tensor.less\_equal.md) | :white\_check\_mark: | +| [Abs](operators/tensor/tensor.abs.md) | :white\_check\_mark: | +| [Ceil](operators/tensor/tensor.ceil.md) | :white\_check\_mark: | +| [Exp](operators/tensor/tensor.exp.md) | :white\_check\_mark: | +| [Ln](operators/tensor/tensor.ln.md) | :white\_check\_mark: | +| [Reshape](operators/tensor/tensor.reshape.md) | :white\_check\_mark: | +| [Transpose](operators/tensor/tensor.transpose.md) | :white\_check\_mark: | +| [ArgMax](operators/tensor/tensor.argmax.md) | :white\_check\_mark: | +| [ArgMin](operators/tensor/tensor.argmin.md) | :white\_check\_mark: | +| [ReduceSum](operators/tensor/tensor.reduce\_sum.md) | :white\_check\_mark: | +| [CumSum](operators/tensor/tensor.cumsum.md) | :white\_check\_mark: | +| [Relu](operators/neural-network/nn.relu.md) | :white\_check\_mark: | +| [LeakyRelu](operators/neural-network/nn.leaky\_relu.md) | :white\_check\_mark: | +| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white\_check\_mark: | +| [Softmax](operators/neural-network/nn.softmax.md) | :white\_check\_mark: | +| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white\_check\_mark: | +| [Softsign](operators/neural-network/nn.softsign.md) | :white\_check\_mark: | +| [Softplus](operators/neural-network/nn.softplus.md) | :white\_check\_mark: | +| [Linear](operators/neural-network/nn.linear.md) | :white\_check\_mark: | +| [Sinh](operators/tensor/tensor.sinh.md) | :white\_check\_mark: | + Performance optimizations: -| Optimization | Implemented | -| :----------------: | :----------------: | -| 8-bit quantization | :white_check_mark: | +| Optimization | Implemented | +| :----------------: | :------------------: | +| 8-bit quantization | :white\_check\_mark: | -Current Operators support: **28/156 (18%)** +Current Operators support: **28/156 (18%)** \ No newline at end of file From 2428947102e740e61ec024a3130a23a0041d9792 Mon Sep 17 00:00:00 2001 From: Roy Date: Wed, 28 Jun 2023 17:46:46 -0700 Subject: [PATCH 063/126] added cosh w/ tests --- docs/CHANGELOG.md | 6 + docs/apis/compatibility.md | 74 ++++++------ docs/apis/numbers/fixed-point/fp.cosh.md | 28 +++++ docs/apis/numbers/fixed-point/fp.sinh.md | 4 +- docs/apis/operators/tensor/tensor.cosh.md | 34 ++++++ docs/apis/operators/tensor/tensor.sinh.md | 9 +- src/numbers/fixed_point/core.cairo | 30 +++++ .../implementations/impl_16x16.cairo | 5 + .../implementations/impl_8x23.cairo | 4 + src/numbers/fixed_point/math/math_16x16.cairo | 8 ++ src/numbers/fixed_point/math/math_8x23.cairo | 8 ++ src/operators/tensor/core.cairo | 40 ++++++- .../implementations/impl_tensor_fp.cairo | 5 + .../implementations/impl_tensor_i32.cairo | 5 + .../implementations/impl_tensor_u32.cairo | 6 + src/operators/tensor/math.cairo | 1 + src/operators/tensor/math/cosh.cairo | 3 + src/operators/tensor/math/cosh/cosh_fp.cairo | 3 + .../tensor/math/cosh/cosh_fp/core.cairo | 18 +++ .../tensor/math/cosh/cosh_fp/fp16x16.cairo | 28 +++++ .../tensor/math/cosh/cosh_fp/fp8x23.cairo | 28 +++++ src/operators/tensor/math/cosh/cosh_i32.cairo | 3 + .../tensor/math/cosh/cosh_i32/core.cairo | 19 +++ .../tensor/math/cosh/cosh_i32/fp16x16.cairo | 37 ++++++ .../tensor/math/cosh/cosh_i32/fp8x23.cairo | 37 ++++++ src/operators/tensor/math/cosh/cosh_u32.cairo | 3 + .../tensor/math/cosh/cosh_u32/core.cairo | 19 +++ .../tensor/math/cosh/cosh_u32/fp16x16.cairo | 31 +++++ .../tensor/math/cosh/cosh_u32/fp8x23.cairo | 31 +++++ .../numbers/fixed_point/fp16x16_test.cairo | 7 ++ .../numbers/fixed_point/fp8x23_test.cairo | 7 ++ src/tests/operators/tensor/math.cairo | 1 + src/tests/operators/tensor/math/cosh.cairo | 3 + .../tensor/math/cosh/cosh_fp_test.cairo | 2 + .../cosh/cosh_fp_test/cosh_fp16x16_test.cairo | 79 ++++++++++++ .../cosh/cosh_fp_test/cosh_fp8x23_test.cairo | 81 +++++++++++++ .../tensor/math/cosh/cosh_i32_test.cairo | 113 ++++++++++++++++++ .../tensor/math/cosh/cosh_u32_test.cairo | 110 +++++++++++++++++ 38 files changed, 884 insertions(+), 46 deletions(-) create mode 100644 docs/apis/numbers/fixed-point/fp.cosh.md create mode 100644 docs/apis/operators/tensor/tensor.cosh.md create mode 100644 src/operators/tensor/math/cosh.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_fp.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_fp/core.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_fp/fp16x16.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_fp/fp8x23.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_i32.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_i32/core.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_i32/fp16x16.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_i32/fp8x23.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_u32.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_u32/core.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_u32/fp16x16.cairo create mode 100644 src/operators/tensor/math/cosh/cosh_u32/fp8x23.cairo create mode 100644 src/tests/operators/tensor/math/cosh.cairo create mode 100644 src/tests/operators/tensor/math/cosh/cosh_fp_test.cairo create mode 100644 src/tests/operators/tensor/math/cosh/cosh_fp_test/cosh_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/math/cosh/cosh_fp_test/cosh_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/math/cosh/cosh_i32_test.cairo create mode 100644 src/tests/operators/tensor/math/cosh/cosh_u32_test.cairo diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 404f8de0d..c6616f7c1 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] - 2023-06-28 + +### Added + +- Added cosh operator + ## [Unreleased] - 2023-06-27 ### Added diff --git a/docs/apis/compatibility.md b/docs/apis/compatibility.md index f10368f7f..ad2023954 100644 --- a/docs/apis/compatibility.md +++ b/docs/apis/compatibility.md @@ -4,44 +4,44 @@ To see the full list of available ONNX Operators refer to [this table](https://g You can see below the list of current supported ONNX Operators: -| Operator | Implemented | -| :---------------------------------------------------------: | :------------------: | -| [MatMul](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | -| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | -| [Add](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Sub](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Mul](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Div](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Equal](operators/tensor/tensor.eq.md) | :white\_check\_mark: | -| [Greater](operators/tensor/tensor.greater.md) | :white\_check\_mark: | -| [GreaterOrEqual](operators/tensor/tensor.greater\_equal.md) | :white\_check\_mark: | -| [Less](operators/tensor/tensor.less.md) | :white\_check\_mark: | -| [LessOrEqual](operators/tensor/tensor.less\_equal.md) | :white\_check\_mark: | -| [Abs](operators/tensor/tensor.abs.md) | :white\_check\_mark: | -| [Ceil](operators/tensor/tensor.ceil.md) | :white\_check\_mark: | -| [Exp](operators/tensor/tensor.exp.md) | :white\_check\_mark: | -| [Ln](operators/tensor/tensor.ln.md) | :white\_check\_mark: | -| [Reshape](operators/tensor/tensor.reshape.md) | :white\_check\_mark: | -| [Transpose](operators/tensor/tensor.transpose.md) | :white\_check\_mark: | -| [ArgMax](operators/tensor/tensor.argmax.md) | :white\_check\_mark: | -| [ArgMin](operators/tensor/tensor.argmin.md) | :white\_check\_mark: | -| [ReduceSum](operators/tensor/tensor.reduce\_sum.md) | :white\_check\_mark: | -| [CumSum](operators/tensor/tensor.cumsum.md) | :white\_check\_mark: | -| [Relu](operators/neural-network/nn.relu.md) | :white\_check\_mark: | -| [LeakyRelu](operators/neural-network/nn.leaky\_relu.md) | :white\_check\_mark: | -| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white\_check\_mark: | -| [Softmax](operators/neural-network/nn.softmax.md) | :white\_check\_mark: | -| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white\_check\_mark: | -| [Softsign](operators/neural-network/nn.softsign.md) | :white\_check\_mark: | -| [Softplus](operators/neural-network/nn.softplus.md) | :white\_check\_mark: | -| [Linear](operators/neural-network/nn.linear.md) | :white\_check\_mark: | -| [Sinh](operators/tensor/tensor.sinh.md) | :white\_check\_mark: | - +| Operator | Implemented | +| :--------------------------------------------------------: | :----------------: | +| [MatMul](operators/tensor/tensor.matmul.md) | :white_check_mark: | +| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white_check_mark: | +| [Add](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Sub](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Mul](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Div](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Equal](operators/tensor/tensor.eq.md) | :white_check_mark: | +| [Greater](operators/tensor/tensor.greater.md) | :white_check_mark: | +| [GreaterOrEqual](operators/tensor/tensor.greater_equal.md) | :white_check_mark: | +| [Less](operators/tensor/tensor.less.md) | :white_check_mark: | +| [LessOrEqual](operators/tensor/tensor.less_equal.md) | :white_check_mark: | +| [Abs](operators/tensor/tensor.abs.md) | :white_check_mark: | +| [Ceil](operators/tensor/tensor.ceil.md) | :white_check_mark: | +| [Exp](operators/tensor/tensor.exp.md) | :white_check_mark: | +| [Ln](operators/tensor/tensor.ln.md) | :white_check_mark: | +| [Reshape](operators/tensor/tensor.reshape.md) | :white_check_mark: | +| [Transpose](operators/tensor/tensor.transpose.md) | :white_check_mark: | +| [ArgMax](operators/tensor/tensor.argmax.md) | :white_check_mark: | +| [ArgMin](operators/tensor/tensor.argmin.md) | :white_check_mark: | +| [ReduceSum](operators/tensor/tensor.reduce_sum.md) | :white_check_mark: | +| [CumSum](operators/tensor/tensor.cumsum.md) | :white_check_mark: | +| [Relu](operators/neural-network/nn.relu.md) | :white_check_mark: | +| [LeakyRelu](operators/neural-network/nn.leaky_relu.md) | :white_check_mark: | +| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white_check_mark: | +| [Softmax](operators/neural-network/nn.softmax.md) | :white_check_mark: | +| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white_check_mark: | +| [Softsign](operators/neural-network/nn.softsign.md) | :white_check_mark: | +| [Softplus](operators/neural-network/nn.softplus.md) | :white_check_mark: | +| [Linear](operators/neural-network/nn.linear.md) | :white_check_mark: | +| [Sinh](operators/tensor/tensor.sinh.md) | :white_check_mark: | +| [Cosh](operators/tensor/tensor.cosh.md) | :white_check_mark: | Performance optimizations: -| Optimization | Implemented | -| :----------------: | :------------------: | -| 8-bit quantization | :white\_check\_mark: | +| Optimization | Implemented | +| :----------------: | :----------------: | +| 8-bit quantization | :white_check_mark: | -Current Operators support: **28/156 (18%)** \ No newline at end of file +Current Operators support: **29/156 (18%)** diff --git a/docs/apis/numbers/fixed-point/fp.cosh.md b/docs/apis/numbers/fixed-point/fp.cosh.md new file mode 100644 index 000000000..c92f572d8 --- /dev/null +++ b/docs/apis/numbers/fixed-point/fp.cosh.md @@ -0,0 +1,28 @@ +# fp.cosh + +```rust +fn cosh(self: FixedType) -> FixedType; +``` + +Returns the value of the hyperbolic cosine of the fixed point number. + +## Args + +- `self`(`FixedType`) - The input fixed point + +## Returns + +The hyperbolic cosine of the input fixed point number. + +## Examples + +```rust +fn cosh_fp_example() -> FixedType { +// We instantiate fixed point here. +let fp = FixedTrait::from_unscaled_felt(2); + +// We can call `cosh` function as follows. +fp.cosh() +} +>>> {mag: 31559577, sign: false} // = 3.62686... +``` diff --git a/docs/apis/numbers/fixed-point/fp.sinh.md b/docs/apis/numbers/fixed-point/fp.sinh.md index 2437bdd10..80f4b7f5d 100644 --- a/docs/apis/numbers/fixed-point/fp.sinh.md +++ b/docs/apis/numbers/fixed-point/fp.sinh.md @@ -8,7 +8,7 @@ Returns the value of the hyperbolic sine of the fixed point number. ## Args -- `self`(`FixedType`) - The input fixed point +* `self`(`FixedType`) - The input fixed point ## Returns @@ -24,5 +24,5 @@ let fp = FixedTrait::from_unscaled_felt(2); // We can call `sinh` function as follows. fp.sinh() } ->>> {mag: 30424303, sign: false} // = 3.6268604 +>>> {mag: 30424311, sign: false} // = 3.6268604 ``` diff --git a/docs/apis/operators/tensor/tensor.cosh.md b/docs/apis/operators/tensor/tensor.cosh.md new file mode 100644 index 000000000..52e68a298 --- /dev/null +++ b/docs/apis/operators/tensor/tensor.cosh.md @@ -0,0 +1,34 @@ +# tensor.cosh + +```rust +fn cosh(self: @Tensor) -> Tensor; +``` + +Computes the hyperbolic cosine of all elements of the input tensor. +$$ +y_i=cosh({x_i}) +$$ + +## Args + +* `self`(`@Tensor`) - The input tensor. + +## Returns + +Returns a new tensor in `FixedType` with the hyperblic cosine of the elements of the input tensor. + +## Examples + +```rust +fn exp_example() -> Tensor { +// We instantiate a 2D Tensor here. +// [[0,1],[2,3]] +let tensor = u32_tensor_2x2_helper(); + +// We can call `cosh` function as follows. +return tensor.cosh(); +} +>>> [[9858303,12944299],[31559585,84453670]] +// The fixed point representation of +// [[0, 1.54308],[3.762196, 10.067662]] +``` diff --git a/docs/apis/operators/tensor/tensor.sinh.md b/docs/apis/operators/tensor/tensor.sinh.md index 575472f97..fca23c6d2 100644 --- a/docs/apis/operators/tensor/tensor.sinh.md +++ b/docs/apis/operators/tensor/tensor.sinh.md @@ -4,19 +4,18 @@ fn sinh(self: @Tensor) -> Tensor; ``` -Computes the exponential of all elements of the input tensor. - +Computes the hyperbolic sine of all elements of the input tensor. $$ y_i=sinh({x_i}) $$ ## Args -- `self`(`@Tensor`) - The input tensor. +* `self`(`@Tensor`) - The input tensor. ## Returns -Returns a new tensor in `FixedType` with the exponential of the elements of the input tensor. +Returns a new tensor in `FixedType` with the hyperbolic sine of the elements of the input tensor. ## Examples @@ -29,7 +28,7 @@ let tensor = u32_tensor_2x2_helper(); // We can call `sinh` function as follows. return tensor.sinh(); } ->>> [[0,9858303],[30424303,84036026]] +>>> [[0,9858303],[30424311,84036026]] // The fixed point representation of // [[0, 1.175201],[3.62686, 10.0178749]] ``` diff --git a/src/numbers/fixed_point/core.cairo b/src/numbers/fixed_point/core.cairo index 0fd88c80b..243a6b626 100644 --- a/src/numbers/fixed_point/core.cairo +++ b/src/numbers/fixed_point/core.cairo @@ -511,4 +511,34 @@ trait FixedTrait { /// ``` /// fn sinh(self: FixedType) -> FixedType; + /// # fp.cosh + /// + /// ```rust + /// fn cosh(self: FixedType) -> FixedType; + /// ``` + /// + /// Returns the value of the hyperbolic cosine of the fixed point number. + /// + /// ## Args + /// + /// * `self`(`FixedType`) - The input fixed point + /// + /// ## Returns + /// + /// The hyperbolic cosine of the input fixed point number. + /// + /// ## Examples + /// + /// ```rust + /// fn cosh_fp_example() -> FixedType { + /// // We instantiate fixed point here. + /// let fp = FixedTrait::from_unscaled_felt(2); + /// + /// // We can call `cosh` function as follows. + /// fp.cosh() + /// } + /// >>> {mag: 31559585, sign: false} // = 3.762195... + /// ``` + /// + fn cosh(self: FixedType) -> FixedType; } diff --git a/src/numbers/fixed_point/implementations/impl_16x16.cairo b/src/numbers/fixed_point/implementations/impl_16x16.cairo index d5d6efaca..0a821adfa 100644 --- a/src/numbers/fixed_point/implementations/impl_16x16.cairo +++ b/src/numbers/fixed_point/implementations/impl_16x16.cairo @@ -85,6 +85,11 @@ impl FP16x16Impl of FixedTrait { fn sinh(self: FixedType) -> FixedType { return math_16x16::sinh(self); } + + fn cosh(self: FixedType) -> FixedType { + return math_16x16::cosh(self); + } + } impl FP16x16Print of PrintTrait { diff --git a/src/numbers/fixed_point/implementations/impl_8x23.cairo b/src/numbers/fixed_point/implementations/impl_8x23.cairo index 16869e291..a9cd0b3d7 100644 --- a/src/numbers/fixed_point/implementations/impl_8x23.cairo +++ b/src/numbers/fixed_point/implementations/impl_8x23.cairo @@ -85,6 +85,10 @@ impl FP8x23Impl of FixedTrait { fn sinh(self: FixedType) -> FixedType { return math_8x23::sinh(self); } + + fn cosh(self: FixedType) -> FixedType { + return math_8x23::cosh(self); + } } impl FP8x23Print of PrintTrait { diff --git a/src/numbers/fixed_point/math/math_16x16.cairo b/src/numbers/fixed_point/math/math_16x16.cairo index bd8ee85d6..fe3b1abf0 100644 --- a/src/numbers/fixed_point/math/math_16x16.cairo +++ b/src/numbers/fixed_point/math/math_16x16.cairo @@ -461,3 +461,11 @@ fn sinh(a: FixedType) -> FixedType { let denom = FixedTrait::new_unscaled(2_u128, false); num / denom } + +/// Cf: FixedTrait::cosh docstring +fn cosh(a: FixedType) -> FixedType { + let ea = a.exp(); + let num = ea + (FixedTrait::new(ONE, false) / ea); + let denom = FixedTrait::new_unscaled(2_u128, false); + num / denom +} \ No newline at end of file diff --git a/src/numbers/fixed_point/math/math_8x23.cairo b/src/numbers/fixed_point/math/math_8x23.cairo index 8a4616840..4bed0dba7 100644 --- a/src/numbers/fixed_point/math/math_8x23.cairo +++ b/src/numbers/fixed_point/math/math_8x23.cairo @@ -463,3 +463,11 @@ fn sinh(a: FixedType) -> FixedType { let denom = FixedTrait::new_unscaled(2_u128, false); num / denom } + +/// Cf: FixedTrait::cosh docstring +fn cosh(a: FixedType) -> FixedType { + let ea = a.exp(); + let num = ea + (FixedTrait::new(ONE, false) / ea); + let denom = FixedTrait::new_unscaled(2_u128, false); + num / denom +} diff --git a/src/operators/tensor/core.cairo b/src/operators/tensor/core.cairo index 5bbd25a3a..1e3d0a78e 100644 --- a/src/operators/tensor/core.cairo +++ b/src/operators/tensor/core.cairo @@ -1191,7 +1191,7 @@ trait TensorTrait { /// fn sinh(self: @Tensor) -> Tensor; /// ``` /// - /// Computes the exponential of all elements of the input tensor. + /// Computes the hyperbolic sine of all elements of the input tensor. /// $$ /// y_i=sinh({x_i}) /// $$ @@ -1202,7 +1202,7 @@ trait TensorTrait { /// /// ## Returns /// - /// Returns a new tensor in `FixedType` with the exponential of the elements of the input tensor. + /// Returns a new tensor in `FixedType` with the hyperbolic sine of the elements of the input tensor. /// /// ## Examples /// @@ -1221,6 +1221,42 @@ trait TensorTrait { /// ``` /// fn sinh(self: @Tensor) -> Tensor; + /// # tensor.cosh + /// + /// ```rust + /// fn cosh(self: @Tensor) -> Tensor; + /// ``` + /// + /// Computes the hyperbolic cosine of all elements of the input tensor. + /// $$ + /// y_i=cosh({x_i}) + /// $$ + /// + /// ## Args + /// + /// * `self`(`@Tensor`) - The input tensor. + /// + /// ## Returns + /// + /// Returns a new tensor in `FixedType` with the hyperblic cosine of the elements of the input tensor. + /// + /// ## Examples + /// + /// ```rust + /// fn exp_example() -> Tensor { + /// // We instantiate a 2D Tensor here. + /// // [[0,1],[2,3]] + /// let tensor = u32_tensor_2x2_helper(); + /// + /// // We can call `cosh` function as follows. + /// return tensor.cosh(); + /// } + /// >>> [[9858303,12944299],[31559585,84453670]] + /// // The fixed point representation of + /// // [[0, 1.54308],[3.762196, 10.067662]] + /// ``` + /// + fn cosh(self: @Tensor) -> Tensor; } /// Cf: TensorTrait::new docstring diff --git a/src/operators/tensor/implementations/impl_tensor_fp.cairo b/src/operators/tensor/implementations/impl_tensor_fp.cairo index 07bc4bcb2..91863514a 100644 --- a/src/operators/tensor/implementations/impl_tensor_fp.cairo +++ b/src/operators/tensor/implementations/impl_tensor_fp.cairo @@ -29,6 +29,7 @@ use orion::operators::tensor::math::greater::greater_fp::core::greater; use orion::operators::tensor::math::greater_equal::greater_equal_fp::core::greater_equal; use orion::operators::tensor::math::cumsum::cumsum_fp::core::cumsum; use orion::operators::tensor::math::sinh::sinh_fp::core::sinh; +use orion::operators::tensor::math::cosh::cosh_fp::core::cosh; use orion::utils::check_gas; @@ -130,6 +131,10 @@ impl Tensor_fp of TensorTrait { fn sinh(self: @Tensor) -> Tensor { sinh(self).unwrap() } + + fn cosh(self: @Tensor) -> Tensor { + cosh(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_i32.cairo b/src/operators/tensor/implementations/impl_tensor_i32.cairo index feee98048..c3b3daf6e 100644 --- a/src/operators/tensor/implementations/impl_tensor_i32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_i32.cairo @@ -30,6 +30,7 @@ use orion::operators::tensor::math::ln::ln_i32::core::ln_i32; use orion::operators::tensor::math::arithmetic::arithmetic_i32::{add, sub, mul, div}; use orion::operators::tensor::math::cumsum::cumsum_i32::cumsum; use orion::operators::tensor::math::sinh::sinh_i32::core::sinh_i32; +use orion::operators::tensor::math::cosh::cosh_i32::core::cosh_i32; use orion::utils::check_gas; impl Tensor_i32 of TensorTrait { @@ -128,6 +129,10 @@ impl Tensor_i32 of TensorTrait { fn sinh(self: @Tensor) -> Tensor { sinh_i32(self).unwrap() } + + fn cosh(self: @Tensor) -> Tensor { + cosh_i32(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_u32.cairo b/src/operators/tensor/implementations/impl_tensor_u32.cairo index b397d9637..78840c58d 100644 --- a/src/operators/tensor/implementations/impl_tensor_u32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_u32.cairo @@ -29,6 +29,7 @@ use orion::operators::tensor::math::ln::ln_u32::core::ln_u32; use orion::operators::tensor::math::arithmetic::arithmetic_u32::{add, sub, mul, div}; use orion::operators::tensor::math::cumsum::cumsum_u32::cumsum; use orion::operators::tensor::math::sinh::sinh_u32::core::sinh_u32; +use orion::operators::tensor::math::cosh::cosh_u32::core::cosh_u32; use orion::utils::check_gas; impl Tensor_u32 of TensorTrait { @@ -124,9 +125,14 @@ impl Tensor_u32 of TensorTrait { fn cumsum(self: @Tensor, axis: usize, exclusive:Option, reverse:Option) -> Tensor { cumsum(self, axis, exclusive, reverse) } + fn sinh(self: @Tensor) -> Tensor { sinh_u32(self).unwrap() } + + fn cosh(self: @Tensor) -> Tensor { + cosh_u32(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/math.cairo b/src/operators/tensor/math.cairo index 1cd55664f..951e98d9b 100644 --- a/src/operators/tensor/math.cairo +++ b/src/operators/tensor/math.cairo @@ -15,3 +15,4 @@ mod abs; mod ceil; mod cumsum; mod sinh; +mod cosh; diff --git a/src/operators/tensor/math/cosh.cairo b/src/operators/tensor/math/cosh.cairo new file mode 100644 index 000000000..681a9572f --- /dev/null +++ b/src/operators/tensor/math/cosh.cairo @@ -0,0 +1,3 @@ +mod cosh_i32; +mod cosh_u32; +mod cosh_fp; \ No newline at end of file diff --git a/src/operators/tensor/math/cosh/cosh_fp.cairo b/src/operators/tensor/math/cosh/cosh_fp.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_fp.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/cosh/cosh_fp/core.cairo b/src/operators/tensor/math/cosh/cosh_fp/core.cairo new file mode 100644 index 000000000..5d6f922d3 --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_fp/core.cairo @@ -0,0 +1,18 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::operators::tensor::math::cosh::cosh_fp::fp8x23; +use orion::operators::tensor::math::cosh::cosh_fp::fp16x16; + +/// Cf: TensorTrait::cosh docstring +fn cosh(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::cosh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::cosh(self)), + }, + Option::None(_) => Option::Some(fp16x16::cosh(self)), + }, + Option::None(_) => Option::Some(fp16x16::cosh(self)), + } +} diff --git a/src/operators/tensor/math/cosh/cosh_fp/fp16x16.cairo b/src/operators/tensor/math/cosh/cosh_fp/fp16x16.cairo new file mode 100644 index 000000000..b4b66ce4e --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_fp/fp16x16.cairo @@ -0,0 +1,28 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::cosh docstring +fn cosh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + result.append(FixedTrait::cosh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/cosh/cosh_fp/fp8x23.cairo b/src/operators/tensor/math/cosh/cosh_fp/fp8x23.cairo new file mode 100644 index 000000000..6ab14f294 --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_fp/fp8x23.cairo @@ -0,0 +1,28 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::cosh docstring +fn cosh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + result.append(FixedTrait::cosh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/cosh/cosh_i32.cairo b/src/operators/tensor/math/cosh/cosh_i32.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_i32.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/cosh/cosh_i32/core.cairo b/src/operators/tensor/math/cosh/cosh_i32/core.cairo new file mode 100644 index 000000000..70367409a --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_i32/core.cairo @@ -0,0 +1,19 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::math::cosh::cosh_i32::fp8x23; +use orion::operators::tensor::math::cosh::cosh_i32::fp16x16; + +/// Cf: TensorTrait::cosh docstring +fn cosh_i32(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::cosh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::cosh(self)), + }, + Option::None(_) => Option::Some(fp16x16::cosh(self)), + }, + Option::None(_) => Option::Some(fp16x16::cosh(self)), + } +} diff --git a/src/operators/tensor/math/cosh/cosh_i32/fp16x16.cairo b/src/operators/tensor/math/cosh/cosh_i32/fp16x16.cairo new file mode 100644 index 000000000..d77990ec1 --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_i32/fp16x16.cairo @@ -0,0 +1,37 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::cosh docstring +fn cosh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + + if ele.sign == true { + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); + result.append(FixedTrait::cosh(ele)) + } else { + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); + result.append(FixedTrait::cosh(ele)) + } + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/cosh/cosh_i32/fp8x23.cairo b/src/operators/tensor/math/cosh/cosh_i32/fp8x23.cairo new file mode 100644 index 000000000..77663817c --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_i32/fp8x23.cairo @@ -0,0 +1,37 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::cosh docstring +fn cosh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + + if ele.sign == true { + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); + result.append(FixedTrait::cosh(ele)) + } else { + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); + result.append(FixedTrait::cosh(ele)) + } + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/cosh/cosh_u32.cairo b/src/operators/tensor/math/cosh/cosh_u32.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_u32.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/cosh/cosh_u32/core.cairo b/src/operators/tensor/math/cosh/cosh_u32/core.cairo new file mode 100644 index 000000000..e1b67beea --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_u32/core.cairo @@ -0,0 +1,19 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::math::cosh::cosh_u32::fp8x23; +use orion::operators::tensor::math::cosh::cosh_u32::fp16x16; + +/// Cf: TensorTrait::cosh docstring +fn cosh_u32(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::cosh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::cosh(self)), + }, + Option::None(_) => Option::Some(fp16x16::cosh(self)), + }, + Option::None(_) => Option::Some(fp16x16::cosh(self)), + } +} diff --git a/src/operators/tensor/math/cosh/cosh_u32/fp16x16.cairo b/src/operators/tensor/math/cosh/cosh_u32/fp16x16.cairo new file mode 100644 index 000000000..c1be449d6 --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_u32/fp16x16.cairo @@ -0,0 +1,31 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::cosh docstring +fn cosh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = FixedTrait::from_unscaled_felt((*data.pop_front().unwrap()).into()); + + result.append(FixedTrait::cosh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/cosh/cosh_u32/fp8x23.cairo b/src/operators/tensor/math/cosh/cosh_u32/fp8x23.cairo new file mode 100644 index 000000000..d58ac8b43 --- /dev/null +++ b/src/operators/tensor/math/cosh/cosh_u32/fp8x23.cairo @@ -0,0 +1,31 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::cosh docstring +fn cosh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = FixedTrait::from_unscaled_felt((*data.pop_front().unwrap()).into()); + + result.append(FixedTrait::cosh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/tests/numbers/fixed_point/fp16x16_test.cairo b/src/tests/numbers/fixed_point/fp16x16_test.cairo index 1bfcd3d46..c2f9d4127 100644 --- a/src/tests/numbers/fixed_point/fp16x16_test.cairo +++ b/src/tests/numbers/fixed_point/fp16x16_test.cairo @@ -330,3 +330,10 @@ fn test_sinh() { let a = FixedTrait::from_unscaled_felt(1); assert(a.sinh().into() == 77016, 'invalid sinh of 1'); } + +#[test] +#[available_gas(10000000)] +fn test_coshh() { + let a = FixedTrait::from_unscaled_felt(1); + assert(a.cosh().into() == 101125, 'invalid cosh of 1'); +} diff --git a/src/tests/numbers/fixed_point/fp8x23_test.cairo b/src/tests/numbers/fixed_point/fp8x23_test.cairo index bfd26c81a..7a2cc8d75 100644 --- a/src/tests/numbers/fixed_point/fp8x23_test.cairo +++ b/src/tests/numbers/fixed_point/fp8x23_test.cairo @@ -329,4 +329,11 @@ fn test_gt() { fn test_sinh() { let a = FixedTrait::from_unscaled_felt(1); assert(a.sinh().into() == 9858301, 'invalid sinh of 1'); +} + +#[test] +#[available_gas(10000000)] +fn test_coshh() { + let a = FixedTrait::from_unscaled_felt(1); + assert(a.cosh().into() == 12944297, 'invalid cosh of 1'); } \ No newline at end of file diff --git a/src/tests/operators/tensor/math.cairo b/src/tests/operators/tensor/math.cairo index 74a629cde..4d526a0ed 100644 --- a/src/tests/operators/tensor/math.cairo +++ b/src/tests/operators/tensor/math.cairo @@ -15,3 +15,4 @@ mod ln; mod arithmetic; mod cumsum; mod sinh; +mod cosh; \ No newline at end of file diff --git a/src/tests/operators/tensor/math/cosh.cairo b/src/tests/operators/tensor/math/cosh.cairo new file mode 100644 index 000000000..adeea19fa --- /dev/null +++ b/src/tests/operators/tensor/math/cosh.cairo @@ -0,0 +1,3 @@ +mod cosh_u32_test; +mod cosh_i32_test; +mod cosh_fp_test; diff --git a/src/tests/operators/tensor/math/cosh/cosh_fp_test.cairo b/src/tests/operators/tensor/math/cosh/cosh_fp_test.cairo new file mode 100644 index 000000000..4505f78f8 --- /dev/null +++ b/src/tests/operators/tensor/math/cosh/cosh_fp_test.cairo @@ -0,0 +1,2 @@ +mod cosh_fp8x23_test; +mod cosh_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/math/cosh/cosh_fp_test/cosh_fp16x16_test.cairo b/src/tests/operators/tensor/math/cosh/cosh_fp_test/cosh_fp16x16_test.cairo new file mode 100644 index 000000000..8820bfe61 --- /dev/null +++ b/src/tests/operators/tensor/math/cosh/cosh_fp_test/cosh_fp16x16_test.cairo @@ -0,0 +1,79 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.62686...'); + + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 659775, 'result[3] = 10.0179...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.5431...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.7622...'); + assert((*result.at(3).mag).into() == 659775, 'result[3] = 10.0677...'); + assert((*result.at(4).mag).into() == 1789592, 'result[4] = 27.3082...'); + assert((*result.at(5).mag).into() == 4863260, 'result[5] = 74.20995...'); + assert((*result.at(6).mag).into() == 13219025, 'result[6] = 201.7156...'); + assert((*result.at(7).mag).into() == 35933213, 'result[7] = 548.3170...'); + } +} diff --git a/src/tests/operators/tensor/math/cosh/cosh_fp_test/cosh_fp8x23_test.cairo b/src/tests/operators/tensor/math/cosh/cosh_fp_test/cosh_fp8x23_test.cairo new file mode 100644 index 000000000..db7c910e0 --- /dev/null +++ b/src/tests/operators/tensor/math/cosh/cosh_fp_test/cosh_fp8x23_test.cairo @@ -0,0 +1,81 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 8388608, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 12944297, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 31559577, 'result[2] = 3.62686...'); + + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 8388608, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 12944297, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 31559577, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 84453662, 'result[3] = 10.0179...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 8388608, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 12944297, 'result[1] = 1.175201...'); + assert((*result.at(2).mag).into() == 31559577, 'result[2] = 3.62686...'); + assert((*result.at(3).mag).into() == 84453662, 'result[3] = 10.0179...'); + assert((*result.at(4).mag).into() == 229078021, 'result[4] = 27.2899...'); + assert((*result.at(5).mag).into() == 622518053, 'result[5] = 74.209...'); + assert((*result.at(6).mag).into() == 1692113052, 'result[6] = 201.7156...'); + assert((*result.at(7).mag).into() == 4599615728, 'result[7] = 548.3170...'); + } +} + diff --git a/src/tests/operators/tensor/math/cosh/cosh_i32_test.cairo b/src/tests/operators/tensor/math/cosh/cosh_i32_test.cairo new file mode 100644 index 000000000..a6916917a --- /dev/null +++ b/src/tests/operators/tensor/math/cosh/cosh_i32_test.cairo @@ -0,0 +1,113 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.5431...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.7622...'); + assert((*result.at(3).mag).into() == 659775, 'result[3] = 10.0677...'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.5431...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.7622...'); + assert((*result.at(3).mag).into() == 659775, 'result[3] = 10.0677...'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(4, false)); + data.append(IntegerTrait::new(5, false)); + data.append(IntegerTrait::new(6, false)); + data.append(IntegerTrait::new(7, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.5431...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.7622...'); + assert((*result.at(3).mag).into() == 659775, 'result[3] = 10.0677...'); + assert((*result.at(4).mag).into() == 1789592, 'result[4] = 27.3082...'); + assert((*result.at(5).mag).into() == 4863260, 'result[5] = 74.20995...'); + assert((*result.at(6).mag).into() == 13219025, 'result[6] = 201.7156...'); + assert((*result.at(7).mag).into() == 35933213, 'result[7] = 548.3170...'); + } +} + diff --git a/src/tests/operators/tensor/math/cosh/cosh_u32_test.cairo b/src/tests/operators/tensor/math/cosh/cosh_u32_test.cairo new file mode 100644 index 000000000..06b581a31 --- /dev/null +++ b/src/tests/operators/tensor/math/cosh/cosh_u32_test.cairo @@ -0,0 +1,110 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.5431...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.7622...'); + assert((*result.at(3).mag).into() == 659775, 'result[3] = 10.0677...'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.5431...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.7622...'); + assert((*result.at(3).mag).into() == 659775, 'result[3] = 10.0677...'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_cosh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + data.append(4); + data.append(5); + data.append(6); + data.append(7); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.cosh().data; + + assert((*result.at(0).mag).into() == 65536, 'result[0] = 1'); + assert((*result.at(1).mag).into() == 101125, 'result[1] = 1.5431...'); + assert((*result.at(2).mag).into() == 246550, 'result[2] = 3.7622...'); + assert((*result.at(3).mag).into() == 659775, 'result[3] = 10.0677...'); + assert((*result.at(4).mag).into() == 1789592, 'result[4] = 27.3082...'); + assert((*result.at(5).mag).into() == 4863260, 'result[5] = 74.20995...'); + assert((*result.at(6).mag).into() == 13219025, 'result[6] = 201.7156...'); + assert((*result.at(7).mag).into() == 35933213, 'result[7] = 548.3170...'); + } +} + From 300052f6a45baee0cd3a2e3eeee1f487035c5087 Mon Sep 17 00:00:00 2001 From: Roy Date: Wed, 28 Jun 2023 20:29:19 -0700 Subject: [PATCH 064/126] added tanh w/ tests --- docs/CHANGELOG.md | 6 + docs/SUMMARY.md | 139 +++++++++--------- docs/apis/compatibility.md | 74 +++++----- docs/apis/numbers/fixed-point/fp.sinh.md | 4 +- docs/apis/numbers/fixed-point/fp.tanh.md | 28 ++++ docs/apis/operators/tensor/tensor.sinh.md | 5 +- docs/apis/operators/tensor/tensor.tanh.md | 34 +++++ src/numbers/fixed_point/core.cairo | 30 ++++ .../implementations/impl_16x16.cairo | 4 + .../implementations/impl_8x23.cairo | 4 + src/numbers/fixed_point/math/math_16x16.cairo | 8 + src/numbers/fixed_point/math/math_8x23.cairo | 8 + src/operators/tensor/core.cairo | 36 +++++ .../implementations/impl_tensor_fp.cairo | 5 + .../implementations/impl_tensor_i32.cairo | 5 + .../implementations/impl_tensor_u32.cairo | 6 + src/operators/tensor/math.cairo | 1 + src/operators/tensor/math/tanh.cairo | 3 + src/operators/tensor/math/tanh/tanh_fp.cairo | 3 + .../tensor/math/tanh/tanh_fp/core.cairo | 18 +++ .../tensor/math/tanh/tanh_fp/fp16x16.cairo | 28 ++++ .../tensor/math/tanh/tanh_fp/fp8x23.cairo | 28 ++++ src/operators/tensor/math/tanh/tanh_i32.cairo | 3 + .../tensor/math/tanh/tanh_i32/core.cairo | 19 +++ .../tensor/math/tanh/tanh_i32/fp16x16.cairo | 37 +++++ .../tensor/math/tanh/tanh_i32/fp8x23.cairo | 37 +++++ src/operators/tensor/math/tanh/tanh_u32.cairo | 3 + .../tensor/math/tanh/tanh_u32/core.cairo | 19 +++ .../tensor/math/tanh/tanh_u32/fp16x16.cairo | 31 ++++ .../tensor/math/tanh/tanh_u32/fp8x23.cairo | 31 ++++ .../numbers/fixed_point/fp16x16_test.cairo | 7 + .../numbers/fixed_point/fp8x23_test.cairo | 7 + src/tests/operators/tensor/math.cairo | 1 + src/tests/operators/tensor/math/tanh.cairo | 3 + .../tensor/math/tanh/tanh_fp_test.cairo | 2 + .../tanh/tanh_fp_test/tanh_fp16x16_test.cairo | 96 ++++++++++++ .../tanh/tanh_fp_test/tanh_fp8x23_test.cairo | 81 ++++++++++ .../tensor/math/tanh/tanh_i32_test.cairo | 113 ++++++++++++++ .../tensor/math/tanh/tanh_u32_test.cairo | 110 ++++++++++++++ 39 files changed, 966 insertions(+), 111 deletions(-) create mode 100644 docs/apis/numbers/fixed-point/fp.tanh.md create mode 100644 docs/apis/operators/tensor/tensor.tanh.md create mode 100644 src/operators/tensor/math/tanh.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_fp.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_fp/core.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_fp/fp16x16.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_fp/fp8x23.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_i32.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_i32/core.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_i32/fp16x16.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_i32/fp8x23.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_u32.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_u32/core.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_u32/fp16x16.cairo create mode 100644 src/operators/tensor/math/tanh/tanh_u32/fp8x23.cairo create mode 100644 src/tests/operators/tensor/math/tanh.cairo create mode 100644 src/tests/operators/tensor/math/tanh/tanh_fp_test.cairo create mode 100644 src/tests/operators/tensor/math/tanh/tanh_fp_test/tanh_fp16x16_test.cairo create mode 100644 src/tests/operators/tensor/math/tanh/tanh_fp_test/tanh_fp8x23_test.cairo create mode 100644 src/tests/operators/tensor/math/tanh/tanh_i32_test.cairo create mode 100644 src/tests/operators/tensor/math/tanh/tanh_u32_test.cairo diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 404f8de0d..ae9db4777 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,6 +8,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Added +- Added tanh operator + +## [Unreleased] - 2023-06-27 + +### Added + - Added sinh operator ## [Unreleased] - 2023-06-24 diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index fa72c8f5f..aa261dae4 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -2,81 +2,82 @@ ## 👋 Welcome -* [Orion](README.md) -* [Why Validity ML?](welcome/why-validity-ml.md) +- [Orion](README.md) +- [Why Validity ML?](welcome/why-validity-ml.md) ## 🧱 APIs -* [Get Started](apis/get-started.md) -* [Compatibility](apis/compatibility.md) -* [Operators](apis/operators/README.md) - * [Tensor](apis/operators/tensor/README.md) - * [tensor.new](apis/operators/tensor/tensor.new.md) - * [tensor.at](apis/operators/tensor/tensor.at.md) - * [tensor.min](apis/operators/tensor/tensor.min.md) - * [tensor.max](apis/operators/tensor/tensor.max.md) - * [tensor.stride](apis/operators/tensor/tensor.stride.md) - * [tensor.ravel\_index](apis/operators/tensor/tensor.ravel\_index.md) - * [tensor.unravel\_index](apis/operators/tensor/tensor.unravel\_index.md) - * [tensor.reshape](apis/operators/tensor/tensor.reshape.md) - * [tensor.transpose](apis/operators/tensor/tensor.transpose.md) - * [tensor.reduce\_sum](apis/operators/tensor/tensor.reduce\_sum.md) - * [tensor.argmax](apis/operators/tensor/tensor.argmax.md) - * [tensor.argmin](apis/operators/tensor/tensor.argmin.md) - * [tensor.matmul](apis/operators/tensor/tensor.matmul.md) - * [tensor.exp](apis/operators/tensor/tensor.exp.md) - * [tensor.ln](apis/operators/tensor/tensor.ln.md) - * [tensor.eq](apis/operators/tensor/tensor.eq.md) - * [tensor.greater](apis/operators/tensor/tensor.greater.md) - * [tensor.greater\_equal](apis/operators/tensor/tensor.greater\_equal.md) - * [tensor.less](apis/operators/tensor/tensor.less.md) - * [tensor.less\_equal](apis/operators/tensor/tensor.less\_equal.md) - * [tensor.abs](apis/operators/tensor/tensor.abs.md) - * [tensor.ceil](apis/operators/tensor/tensor.ceil.md) - * [tensor.cumsum](apis/operators/tensor/tensor.cumsum.md) - * [tensor.sinh](apis/operators/tensor/tensor.sinh.md) - * [Neural Network](apis/operators/neural-network/README.md) - * [nn.relu](apis/operators/neural-network/nn.relu.md) - * [nn.leaky\_relu](apis/operators/neural-network/nn.leaky\_relu.md) - * [nn.sigmoid](apis/operators/neural-network/nn.sigmoid.md) - * [nn.softmax](apis/operators/neural-network/nn.softmax.md) - * [nn.logsoftmax](apis/operators/neural-network/nn.logsoftmax.md) - * [nn.softsign](apis/operators/neural-network/nn.softsign.md) - * [nn.softplus](apis/operators/neural-network/nn.softplus.md) - * [nn.linear](apis/operators/neural-network/nn.linear.md) -* [Numbers](apis/numbers/README.md) - * [Signed Integer](apis/numbers/signed-integer/README.md) - * [int.new](apis/numbers/signed-integer/int.new.md) - * [int.div\_rem](apis/numbers/signed-integer/int.div\_rem.md) - * [int.abs](apis/numbers/signed-integer/int.abs.md) - * [int.max](apis/numbers/signed-integer/int.max.md) - * [int.min](apis/numbers/signed-integer/int.min.md) - * [Fixed Point](apis/numbers/fixed-point/README.md) - * [fp.new](apis/numbers/fixed-point/fp.new.md) - * [fp.new\_unscaled](apis/numbers/fixed-point/fp.new\_unscaled.md) - * [fp.from\_felt](apis/numbers/fixed-point/fp.from\_felt.md) - * [fp.from\_unscaled\_felt](apis/numbers/fixed-point/fp.from\_unscaled\_felt.md) - * [fp.abs](apis/numbers/fixed-point/fp.abs.md) - * [fp.ceil](apis/numbers/fixed-point/fp.ceil.md) - * [fp.floor](apis/numbers/fixed-point/fp.floor.md) - * [fp.exp](apis/numbers/fixed-point/fp.exp.md) - * [fp.exp2](apis/numbers/fixed-point/fp.exp2.md) - * [fp.ln](apis/numbers/fixed-point/fp.ln.md) - * [fp.log2](apis/numbers/fixed-point/fp.log2.md) - * [fp.log10](apis/numbers/fixed-point/fp.log10.md) - * [fp.pow](apis/numbers/fixed-point/fp.pow.md) - * [fp.round](apis/numbers/fixed-point/fp.round.md) - * [fp.sqrt](apis/numbers/fixed-point/fp.sqrt.md) -* [Performance](apis/performance/README.md) - * [performance.quantize\_linear](apis/performance/performance.quantize\_linear.md) - * [performance.quantize\_linear\_from\_fp](apis/performance/performance.quantize\_linear\_from\_fp.md) +- [Get Started](apis/get-started.md) +- [Compatibility](apis/compatibility.md) +- [Operators](apis/operators/README.md) + - [Tensor](apis/operators/tensor/README.md) + - [tensor.new](apis/operators/tensor/tensor.new.md) + - [tensor.at](apis/operators/tensor/tensor.at.md) + - [tensor.min](apis/operators/tensor/tensor.min.md) + - [tensor.max](apis/operators/tensor/tensor.max.md) + - [tensor.stride](apis/operators/tensor/tensor.stride.md) + - [tensor.ravel_index](apis/operators/tensor/tensor.ravel_index.md) + - [tensor.unravel_index](apis/operators/tensor/tensor.unravel_index.md) + - [tensor.reshape](apis/operators/tensor/tensor.reshape.md) + - [tensor.transpose](apis/operators/tensor/tensor.transpose.md) + - [tensor.reduce_sum](apis/operators/tensor/tensor.reduce_sum.md) + - [tensor.argmax](apis/operators/tensor/tensor.argmax.md) + - [tensor.argmin](apis/operators/tensor/tensor.argmin.md) + - [tensor.matmul](apis/operators/tensor/tensor.matmul.md) + - [tensor.exp](apis/operators/tensor/tensor.exp.md) + - [tensor.ln](apis/operators/tensor/tensor.ln.md) + - [tensor.eq](apis/operators/tensor/tensor.eq.md) + - [tensor.greater](apis/operators/tensor/tensor.greater.md) + - [tensor.greater_equal](apis/operators/tensor/tensor.greater_equal.md) + - [tensor.less](apis/operators/tensor/tensor.less.md) + - [tensor.less_equal](apis/operators/tensor/tensor.less_equal.md) + - [tensor.abs](apis/operators/tensor/tensor.abs.md) + - [tensor.ceil](apis/operators/tensor/tensor.ceil.md) + - [tensor.cumsum](apis/operators/tensor/tensor.cumsum.md) + - [tensor.sinh](apis/operators/tensor/tensor.sinh.md) + - [tensor.tanh](apis/operators/tensor/tensor.tanh.md) + - [Neural Network](apis/operators/neural-network/README.md) + - [nn.relu](apis/operators/neural-network/nn.relu.md) + - [nn.leaky_relu](apis/operators/neural-network/nn.leaky_relu.md) + - [nn.sigmoid](apis/operators/neural-network/nn.sigmoid.md) + - [nn.softmax](apis/operators/neural-network/nn.softmax.md) + - [nn.logsoftmax](apis/operators/neural-network/nn.logsoftmax.md) + - [nn.softsign](apis/operators/neural-network/nn.softsign.md) + - [nn.softplus](apis/operators/neural-network/nn.softplus.md) + - [nn.linear](apis/operators/neural-network/nn.linear.md) +- [Numbers](apis/numbers/README.md) + - [Signed Integer](apis/numbers/signed-integer/README.md) + - [int.new](apis/numbers/signed-integer/int.new.md) + - [int.div_rem](apis/numbers/signed-integer/int.div_rem.md) + - [int.abs](apis/numbers/signed-integer/int.abs.md) + - [int.max](apis/numbers/signed-integer/int.max.md) + - [int.min](apis/numbers/signed-integer/int.min.md) + - [Fixed Point](apis/numbers/fixed-point/README.md) + - [fp.new](apis/numbers/fixed-point/fp.new.md) + - [fp.new_unscaled](apis/numbers/fixed-point/fp.new_unscaled.md) + - [fp.from_felt](apis/numbers/fixed-point/fp.from_felt.md) + - [fp.from_unscaled_felt](apis/numbers/fixed-point/fp.from_unscaled_felt.md) + - [fp.abs](apis/numbers/fixed-point/fp.abs.md) + - [fp.ceil](apis/numbers/fixed-point/fp.ceil.md) + - [fp.floor](apis/numbers/fixed-point/fp.floor.md) + - [fp.exp](apis/numbers/fixed-point/fp.exp.md) + - [fp.exp2](apis/numbers/fixed-point/fp.exp2.md) + - [fp.ln](apis/numbers/fixed-point/fp.ln.md) + - [fp.log2](apis/numbers/fixed-point/fp.log2.md) + - [fp.log10](apis/numbers/fixed-point/fp.log10.md) + - [fp.pow](apis/numbers/fixed-point/fp.pow.md) + - [fp.round](apis/numbers/fixed-point/fp.round.md) + - [fp.sqrt](apis/numbers/fixed-point/fp.sqrt.md) +- [Performance](apis/performance/README.md) + - [performance.quantize_linear](apis/performance/performance.quantize_linear.md) + - [performance.quantize_linear_from_fp](apis/performance/performance.quantize_linear_from_fp.md) ## 💖 Community -* [Algorithms](community/algorithms.md) -* [Contribute](community/contribute.md) +- [Algorithms](community/algorithms.md) +- [Contribute](community/contribute.md) ## 📖 Resources -* [Tutorials](resources/tutorials/README.md) - * [MNIST Classification with Orion](resources/tutorials/mnist-classification-with-orion.md) +- [Tutorials](resources/tutorials/README.md) + - [MNIST Classification with Orion](resources/tutorials/mnist-classification-with-orion.md) diff --git a/docs/apis/compatibility.md b/docs/apis/compatibility.md index f10368f7f..e51a2bbe3 100644 --- a/docs/apis/compatibility.md +++ b/docs/apis/compatibility.md @@ -4,44 +4,44 @@ To see the full list of available ONNX Operators refer to [this table](https://g You can see below the list of current supported ONNX Operators: -| Operator | Implemented | -| :---------------------------------------------------------: | :------------------: | -| [MatMul](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | -| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | -| [Add](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Sub](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Mul](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Div](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | -| [Equal](operators/tensor/tensor.eq.md) | :white\_check\_mark: | -| [Greater](operators/tensor/tensor.greater.md) | :white\_check\_mark: | -| [GreaterOrEqual](operators/tensor/tensor.greater\_equal.md) | :white\_check\_mark: | -| [Less](operators/tensor/tensor.less.md) | :white\_check\_mark: | -| [LessOrEqual](operators/tensor/tensor.less\_equal.md) | :white\_check\_mark: | -| [Abs](operators/tensor/tensor.abs.md) | :white\_check\_mark: | -| [Ceil](operators/tensor/tensor.ceil.md) | :white\_check\_mark: | -| [Exp](operators/tensor/tensor.exp.md) | :white\_check\_mark: | -| [Ln](operators/tensor/tensor.ln.md) | :white\_check\_mark: | -| [Reshape](operators/tensor/tensor.reshape.md) | :white\_check\_mark: | -| [Transpose](operators/tensor/tensor.transpose.md) | :white\_check\_mark: | -| [ArgMax](operators/tensor/tensor.argmax.md) | :white\_check\_mark: | -| [ArgMin](operators/tensor/tensor.argmin.md) | :white\_check\_mark: | -| [ReduceSum](operators/tensor/tensor.reduce\_sum.md) | :white\_check\_mark: | -| [CumSum](operators/tensor/tensor.cumsum.md) | :white\_check\_mark: | -| [Relu](operators/neural-network/nn.relu.md) | :white\_check\_mark: | -| [LeakyRelu](operators/neural-network/nn.leaky\_relu.md) | :white\_check\_mark: | -| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white\_check\_mark: | -| [Softmax](operators/neural-network/nn.softmax.md) | :white\_check\_mark: | -| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white\_check\_mark: | -| [Softsign](operators/neural-network/nn.softsign.md) | :white\_check\_mark: | -| [Softplus](operators/neural-network/nn.softplus.md) | :white\_check\_mark: | -| [Linear](operators/neural-network/nn.linear.md) | :white\_check\_mark: | -| [Sinh](operators/tensor/tensor.sinh.md) | :white\_check\_mark: | - +| Operator | Implemented | +| :--------------------------------------------------------: | :----------------: | +| [MatMul](operators/tensor/tensor.matmul.md) | :white_check_mark: | +| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white_check_mark: | +| [Add](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Sub](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Mul](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Div](operators/tensor/#arithmetic-operations) | :white_check_mark: | +| [Equal](operators/tensor/tensor.eq.md) | :white_check_mark: | +| [Greater](operators/tensor/tensor.greater.md) | :white_check_mark: | +| [GreaterOrEqual](operators/tensor/tensor.greater_equal.md) | :white_check_mark: | +| [Less](operators/tensor/tensor.less.md) | :white_check_mark: | +| [LessOrEqual](operators/tensor/tensor.less_equal.md) | :white_check_mark: | +| [Abs](operators/tensor/tensor.abs.md) | :white_check_mark: | +| [Ceil](operators/tensor/tensor.ceil.md) | :white_check_mark: | +| [Exp](operators/tensor/tensor.exp.md) | :white_check_mark: | +| [Ln](operators/tensor/tensor.ln.md) | :white_check_mark: | +| [Reshape](operators/tensor/tensor.reshape.md) | :white_check_mark: | +| [Transpose](operators/tensor/tensor.transpose.md) | :white_check_mark: | +| [ArgMax](operators/tensor/tensor.argmax.md) | :white_check_mark: | +| [ArgMin](operators/tensor/tensor.argmin.md) | :white_check_mark: | +| [ReduceSum](operators/tensor/tensor.reduce_sum.md) | :white_check_mark: | +| [CumSum](operators/tensor/tensor.cumsum.md) | :white_check_mark: | +| [Relu](operators/neural-network/nn.relu.md) | :white_check_mark: | +| [LeakyRelu](operators/neural-network/nn.leaky_relu.md) | :white_check_mark: | +| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white_check_mark: | +| [Softmax](operators/neural-network/nn.softmax.md) | :white_check_mark: | +| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white_check_mark: | +| [Softsign](operators/neural-network/nn.softsign.md) | :white_check_mark: | +| [Softplus](operators/neural-network/nn.softplus.md) | :white_check_mark: | +| [Linear](operators/neural-network/nn.linear.md) | :white_check_mark: | +| [Sinh](operators/tensor/tensor.sinh.md) | :white_check_mark: | +| [Tanh](operators/tensor/tensor.tanh.md) | :white_check_mark: | Performance optimizations: -| Optimization | Implemented | -| :----------------: | :------------------: | -| 8-bit quantization | :white\_check\_mark: | +| Optimization | Implemented | +| :----------------: | :----------------: | +| 8-bit quantization | :white_check_mark: | -Current Operators support: **28/156 (18%)** \ No newline at end of file +Current Operators support: **29/156 (19%)** diff --git a/docs/apis/numbers/fixed-point/fp.sinh.md b/docs/apis/numbers/fixed-point/fp.sinh.md index 2437bdd10..80f4b7f5d 100644 --- a/docs/apis/numbers/fixed-point/fp.sinh.md +++ b/docs/apis/numbers/fixed-point/fp.sinh.md @@ -8,7 +8,7 @@ Returns the value of the hyperbolic sine of the fixed point number. ## Args -- `self`(`FixedType`) - The input fixed point +* `self`(`FixedType`) - The input fixed point ## Returns @@ -24,5 +24,5 @@ let fp = FixedTrait::from_unscaled_felt(2); // We can call `sinh` function as follows. fp.sinh() } ->>> {mag: 30424303, sign: false} // = 3.6268604 +>>> {mag: 30424311, sign: false} // = 3.6268604 ``` diff --git a/docs/apis/numbers/fixed-point/fp.tanh.md b/docs/apis/numbers/fixed-point/fp.tanh.md new file mode 100644 index 000000000..59a2bec1d --- /dev/null +++ b/docs/apis/numbers/fixed-point/fp.tanh.md @@ -0,0 +1,28 @@ +# fp.tanh + +```rust +fn tanh(self: FixedType) -> FixedType; +``` + +Returns the value of the hyperbolic tangent of the fixed point number. + +## Args + +* `self`(`FixedType`) - The input fixed point + +## Returns + +The hyperbolic tangent of the input fixed point number. + +## Examples + +```rust +fn tanh_fp_example() -> FixedType { +// We instantiate fixed point here. +let fp = FixedTrait::from_unscaled_felt(2); + +// We can call `tanh` function as follows. +fp.tanh() +} +>>> {mag: 8086850, sign: false} // = 0.964027... +``` diff --git a/docs/apis/operators/tensor/tensor.sinh.md b/docs/apis/operators/tensor/tensor.sinh.md index 575472f97..bb95366fe 100644 --- a/docs/apis/operators/tensor/tensor.sinh.md +++ b/docs/apis/operators/tensor/tensor.sinh.md @@ -5,14 +5,13 @@ fn sinh(self: @Tensor) -> Tensor; ``` Computes the exponential of all elements of the input tensor. - $$ y_i=sinh({x_i}) $$ ## Args -- `self`(`@Tensor`) - The input tensor. +* `self`(`@Tensor`) - The input tensor. ## Returns @@ -29,7 +28,7 @@ let tensor = u32_tensor_2x2_helper(); // We can call `sinh` function as follows. return tensor.sinh(); } ->>> [[0,9858303],[30424303,84036026]] +>>> [[0,9858303],[30424311,84036026]] // The fixed point representation of // [[0, 1.175201],[3.62686, 10.0178749]] ``` diff --git a/docs/apis/operators/tensor/tensor.tanh.md b/docs/apis/operators/tensor/tensor.tanh.md new file mode 100644 index 000000000..dafce66f1 --- /dev/null +++ b/docs/apis/operators/tensor/tensor.tanh.md @@ -0,0 +1,34 @@ +# tensor.tanh + +```rust +fn tanh(self: @Tensor) -> Tensor; +``` + +Computes the exponential of all elements of the input tensor. +$$ +y_i=tanh({x_i}) +$$ + +## Args + +* `self`(`@Tensor`) - The input tensor. + +## Returns + +Returns a new tensor in `FixedType` with the exponential of the elements of the input tensor. + +## Examples + +```rust +fn tanh_example() -> Tensor { +// We instantiate a 2D Tensor here. +// [[0,1],[2,3]] +let tensor = u32_tensor_2x2_helper(); + +// We can call `tanh` function as follows. +return tensor.tanh(); +} +>>> [[0,6388715],[8086850,8347125]] +// The fixed point representation of +// [[0, 0.761594],[0.96403, 0.9951]] +``` diff --git a/src/numbers/fixed_point/core.cairo b/src/numbers/fixed_point/core.cairo index 0fd88c80b..1c2e38edb 100644 --- a/src/numbers/fixed_point/core.cairo +++ b/src/numbers/fixed_point/core.cairo @@ -511,4 +511,34 @@ trait FixedTrait { /// ``` /// fn sinh(self: FixedType) -> FixedType; + /// # fp.tanh + /// + /// ```rust + /// fn tanh(self: FixedType) -> FixedType; + /// ``` + /// + /// Returns the value of the hyperbolic tangent of the fixed point number. + /// + /// ## Args + /// + /// * `self`(`FixedType`) - The input fixed point + /// + /// ## Returns + /// + /// The hyperbolic tangent of the input fixed point number. + /// + /// ## Examples + /// + /// ```rust + /// fn tanh_fp_example() -> FixedType { + /// // We instantiate fixed point here. + /// let fp = FixedTrait::from_unscaled_felt(2); + /// + /// // We can call `tanh` function as follows. + /// fp.tanh() + /// } + /// >>> {mag: 8086850, sign: false} // = 0.964027... + /// ``` + /// + fn tanh(self: FixedType) -> FixedType; } diff --git a/src/numbers/fixed_point/implementations/impl_16x16.cairo b/src/numbers/fixed_point/implementations/impl_16x16.cairo index d5d6efaca..36a261f87 100644 --- a/src/numbers/fixed_point/implementations/impl_16x16.cairo +++ b/src/numbers/fixed_point/implementations/impl_16x16.cairo @@ -85,6 +85,10 @@ impl FP16x16Impl of FixedTrait { fn sinh(self: FixedType) -> FixedType { return math_16x16::sinh(self); } + + fn tanh(self: FixedType) -> FixedType { + return math_16x16::tanh(self); + } } impl FP16x16Print of PrintTrait { diff --git a/src/numbers/fixed_point/implementations/impl_8x23.cairo b/src/numbers/fixed_point/implementations/impl_8x23.cairo index 16869e291..34c7435ba 100644 --- a/src/numbers/fixed_point/implementations/impl_8x23.cairo +++ b/src/numbers/fixed_point/implementations/impl_8x23.cairo @@ -85,6 +85,10 @@ impl FP8x23Impl of FixedTrait { fn sinh(self: FixedType) -> FixedType { return math_8x23::sinh(self); } + + fn tanh(self: FixedType) -> FixedType { + return math_8x23::tanh(self); + } } impl FP8x23Print of PrintTrait { diff --git a/src/numbers/fixed_point/math/math_16x16.cairo b/src/numbers/fixed_point/math/math_16x16.cairo index bd8ee85d6..bc17a4dec 100644 --- a/src/numbers/fixed_point/math/math_16x16.cairo +++ b/src/numbers/fixed_point/math/math_16x16.cairo @@ -461,3 +461,11 @@ fn sinh(a: FixedType) -> FixedType { let denom = FixedTrait::new_unscaled(2_u128, false); num / denom } + +/// Cf: FixedTrait::tanh docstring +fn tanh(a: FixedType) -> FixedType { + let ea = a.exp(); + let num = ea - (FixedTrait::new(ONE, false) / ea); + let denom = ea + (FixedTrait::new(ONE, false) / ea); + num / denom +} diff --git a/src/numbers/fixed_point/math/math_8x23.cairo b/src/numbers/fixed_point/math/math_8x23.cairo index 8a4616840..973eff15b 100644 --- a/src/numbers/fixed_point/math/math_8x23.cairo +++ b/src/numbers/fixed_point/math/math_8x23.cairo @@ -463,3 +463,11 @@ fn sinh(a: FixedType) -> FixedType { let denom = FixedTrait::new_unscaled(2_u128, false); num / denom } + +/// Cf: FixedTrait::tanh docstring +fn tanh(a: FixedType) -> FixedType { + let ea = a.exp(); + let num = ea - (FixedTrait::new(ONE, false) / ea); + let denom = ea + (FixedTrait::new(ONE, false) / ea); + num / denom +} diff --git a/src/operators/tensor/core.cairo b/src/operators/tensor/core.cairo index 5bbd25a3a..223c05028 100644 --- a/src/operators/tensor/core.cairo +++ b/src/operators/tensor/core.cairo @@ -1221,6 +1221,42 @@ trait TensorTrait { /// ``` /// fn sinh(self: @Tensor) -> Tensor; + /// # tensor.tanh + /// + /// ```rust + /// fn tanh(self: @Tensor) -> Tensor; + /// ``` + /// + /// Computes the exponential of all elements of the input tensor. + /// $$ + /// y_i=tanh({x_i}) + /// $$ + /// + /// ## Args + /// + /// * `self`(`@Tensor`) - The input tensor. + /// + /// ## Returns + /// + /// Returns a new tensor in `FixedType` with the exponential of the elements of the input tensor. + /// + /// ## Examples + /// + /// ```rust + /// fn tanh_example() -> Tensor { + /// // We instantiate a 2D Tensor here. + /// // [[0,1],[2,3]] + /// let tensor = u32_tensor_2x2_helper(); + /// + /// // We can call `tanh` function as follows. + /// return tensor.tanh(); + /// } + /// >>> [[0,6388715],[8086850,8347125]] + /// // The fixed point representation of + /// // [[0, 0.761594],[0.96403, 0.9951]] + /// ``` + /// + fn tanh(self: @Tensor) -> Tensor; } /// Cf: TensorTrait::new docstring diff --git a/src/operators/tensor/implementations/impl_tensor_fp.cairo b/src/operators/tensor/implementations/impl_tensor_fp.cairo index 07bc4bcb2..980a26fbd 100644 --- a/src/operators/tensor/implementations/impl_tensor_fp.cairo +++ b/src/operators/tensor/implementations/impl_tensor_fp.cairo @@ -29,6 +29,7 @@ use orion::operators::tensor::math::greater::greater_fp::core::greater; use orion::operators::tensor::math::greater_equal::greater_equal_fp::core::greater_equal; use orion::operators::tensor::math::cumsum::cumsum_fp::core::cumsum; use orion::operators::tensor::math::sinh::sinh_fp::core::sinh; +use orion::operators::tensor::math::tanh::tanh_fp::core::tanh; use orion::utils::check_gas; @@ -130,6 +131,10 @@ impl Tensor_fp of TensorTrait { fn sinh(self: @Tensor) -> Tensor { sinh(self).unwrap() } + + fn tanh(self: @Tensor) -> Tensor { + tanh(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_i32.cairo b/src/operators/tensor/implementations/impl_tensor_i32.cairo index feee98048..e310d1b38 100644 --- a/src/operators/tensor/implementations/impl_tensor_i32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_i32.cairo @@ -30,6 +30,7 @@ use orion::operators::tensor::math::ln::ln_i32::core::ln_i32; use orion::operators::tensor::math::arithmetic::arithmetic_i32::{add, sub, mul, div}; use orion::operators::tensor::math::cumsum::cumsum_i32::cumsum; use orion::operators::tensor::math::sinh::sinh_i32::core::sinh_i32; +use orion::operators::tensor::math::tanh::tanh_i32::core::tanh_i32; use orion::utils::check_gas; impl Tensor_i32 of TensorTrait { @@ -128,6 +129,10 @@ impl Tensor_i32 of TensorTrait { fn sinh(self: @Tensor) -> Tensor { sinh_i32(self).unwrap() } + + fn tanh(self: @Tensor) -> Tensor { + tanh_i32(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/implementations/impl_tensor_u32.cairo b/src/operators/tensor/implementations/impl_tensor_u32.cairo index b397d9637..77290f79b 100644 --- a/src/operators/tensor/implementations/impl_tensor_u32.cairo +++ b/src/operators/tensor/implementations/impl_tensor_u32.cairo @@ -29,6 +29,7 @@ use orion::operators::tensor::math::ln::ln_u32::core::ln_u32; use orion::operators::tensor::math::arithmetic::arithmetic_u32::{add, sub, mul, div}; use orion::operators::tensor::math::cumsum::cumsum_u32::cumsum; use orion::operators::tensor::math::sinh::sinh_u32::core::sinh_u32; +use orion::operators::tensor::math::tanh::tanh_u32::core::tanh_u32; use orion::utils::check_gas; impl Tensor_u32 of TensorTrait { @@ -124,9 +125,14 @@ impl Tensor_u32 of TensorTrait { fn cumsum(self: @Tensor, axis: usize, exclusive:Option, reverse:Option) -> Tensor { cumsum(self, axis, exclusive, reverse) } + fn sinh(self: @Tensor) -> Tensor { sinh_u32(self).unwrap() } + + fn tanh(self: @Tensor) -> Tensor { + tanh_u32(self).unwrap() + } } /// Implements addition for `Tensor` using the `Add` trait. diff --git a/src/operators/tensor/math.cairo b/src/operators/tensor/math.cairo index 1cd55664f..d70bba5ba 100644 --- a/src/operators/tensor/math.cairo +++ b/src/operators/tensor/math.cairo @@ -15,3 +15,4 @@ mod abs; mod ceil; mod cumsum; mod sinh; +mod tanh; diff --git a/src/operators/tensor/math/tanh.cairo b/src/operators/tensor/math/tanh.cairo new file mode 100644 index 000000000..b845d9274 --- /dev/null +++ b/src/operators/tensor/math/tanh.cairo @@ -0,0 +1,3 @@ +mod tanh_i32; +mod tanh_u32; +mod tanh_fp; diff --git a/src/operators/tensor/math/tanh/tanh_fp.cairo b/src/operators/tensor/math/tanh/tanh_fp.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_fp.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/tanh/tanh_fp/core.cairo b/src/operators/tensor/math/tanh/tanh_fp/core.cairo new file mode 100644 index 000000000..45f5a1993 --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_fp/core.cairo @@ -0,0 +1,18 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::operators::tensor::math::tanh::tanh_fp::fp8x23; +use orion::operators::tensor::math::tanh::tanh_fp::fp16x16; + +/// Cf: TensorTrait::tanh docstring +fn tanh(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::tanh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::tanh(self)), + }, + Option::None(_) => Option::Some(fp16x16::tanh(self)), + }, + Option::None(_) => Option::Some(fp16x16::tanh(self)), + } +} diff --git a/src/operators/tensor/math/tanh/tanh_fp/fp16x16.cairo b/src/operators/tensor/math/tanh/tanh_fp/fp16x16.cairo new file mode 100644 index 000000000..3a8b8ff8c --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_fp/fp16x16.cairo @@ -0,0 +1,28 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::tanh docstring +fn tanh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + result.append(FixedTrait::tanh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/tanh/tanh_fp/fp8x23.cairo b/src/operators/tensor/math/tanh/tanh_fp/fp8x23.cairo new file mode 100644 index 000000000..fecb8cca8 --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_fp/fp8x23.cairo @@ -0,0 +1,28 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::tanh docstring +fn tanh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + result.append(FixedTrait::tanh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/tanh/tanh_i32.cairo b/src/operators/tensor/math/tanh/tanh_i32.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_i32.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/tanh/tanh_i32/core.cairo b/src/operators/tensor/math/tanh/tanh_i32/core.cairo new file mode 100644 index 000000000..271bbbd7b --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_i32/core.cairo @@ -0,0 +1,19 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::math::tanh::tanh_i32::fp8x23; +use orion::operators::tensor::math::tanh::tanh_i32::fp16x16; + +/// Cf: TensorTrait::tanh docstring +fn tanh_i32(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::tanh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::tanh(self)), + }, + Option::None(_) => Option::Some(fp16x16::tanh(self)), + }, + Option::None(_) => Option::Some(fp16x16::tanh(self)), + } +} diff --git a/src/operators/tensor/math/tanh/tanh_i32/fp16x16.cairo b/src/operators/tensor/math/tanh/tanh_i32/fp16x16.cairo new file mode 100644 index 000000000..5dae7dd89 --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_i32/fp16x16.cairo @@ -0,0 +1,37 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::tanh docstring +fn tanh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + + if ele.sign == true { + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); + result.append(FixedTrait::tanh(ele)) + } else { + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); + result.append(FixedTrait::tanh(ele)) + } + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/tanh/tanh_i32/fp8x23.cairo b/src/operators/tensor/math/tanh/tanh_i32/fp8x23.cairo new file mode 100644 index 000000000..36cab9163 --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_i32/fp8x23.cairo @@ -0,0 +1,37 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::tanh docstring +fn tanh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = *data.pop_front().unwrap(); + + if ele.sign == true { + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); + result.append(FixedTrait::tanh(ele)) + } else { + let ele = FixedTrait::new_unscaled(ele.mag.into(), ele.sign); + result.append(FixedTrait::tanh(ele)) + } + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/tanh/tanh_u32.cairo b/src/operators/tensor/math/tanh/tanh_u32.cairo new file mode 100644 index 000000000..1a2b31adf --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_u32.cairo @@ -0,0 +1,3 @@ +mod core; +mod fp8x23; +mod fp16x16; \ No newline at end of file diff --git a/src/operators/tensor/math/tanh/tanh_u32/core.cairo b/src/operators/tensor/math/tanh/tanh_u32/core.cairo new file mode 100644 index 000000000..dc5e39c0c --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_u32/core.cairo @@ -0,0 +1,19 @@ +use orion::numbers::fixed_point::core::{FixedType, FixedImpl}; +use orion::operators::tensor::core::{Tensor}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::math::tanh::tanh_u32::fp8x23; +use orion::operators::tensor::math::tanh::tanh_u32::fp16x16; + +/// Cf: TensorTrait::tanh docstring +fn tanh_u32(self: @Tensor) -> Option> { + match *self.extra { + Option::Some(extra_params) => match extra_params.fixed_point { + Option::Some(fixed_point) => match fixed_point { + FixedImpl::FP8x23(()) => Option::Some(fp8x23::tanh(self)), + FixedImpl::FP16x16(()) => Option::Some(fp16x16::tanh(self)), + }, + Option::None(_) => Option::Some(fp16x16::tanh(self)), + }, + Option::None(_) => Option::Some(fp16x16::tanh(self)), + } +} diff --git a/src/operators/tensor/math/tanh/tanh_u32/fp16x16.cairo b/src/operators/tensor/math/tanh/tanh_u32/fp16x16.cairo new file mode 100644 index 000000000..b4c46a411 --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_u32/fp16x16.cairo @@ -0,0 +1,31 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::tanh docstring +fn tanh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = FixedTrait::from_unscaled_felt((*data.pop_front().unwrap()).into()); + + result.append(FixedTrait::tanh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/operators/tensor/math/tanh/tanh_u32/fp8x23.cairo b/src/operators/tensor/math/tanh/tanh_u32/fp8x23.cairo new file mode 100644 index 000000000..c68837dab --- /dev/null +++ b/src/operators/tensor/math/tanh/tanh_u32/fp8x23.cairo @@ -0,0 +1,31 @@ +use array::ArrayTrait; +use array::SpanTrait; +use option::OptionTrait; +use traits::Into; + +use orion::numbers::fixed_point::core::{FixedTrait, FixedType}; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::numbers::signed_integer::i32::i32; +use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; +use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; +use orion::utils::check_gas; + +/// Cf: TensorTrait::tanh docstring +fn tanh(self: @Tensor) -> Tensor { + let mut result = ArrayTrait::new(); + let mut data = *self.data; + + loop { + check_gas(); + + let ele = FixedTrait::from_unscaled_felt((*data.pop_front().unwrap()).into()); + + result.append(FixedTrait::tanh(ele)); + + if (data.len() == 0) { + break (); + }; + }; + + return TensorTrait::::new(*self.shape, result.span(), *self.extra); +} diff --git a/src/tests/numbers/fixed_point/fp16x16_test.cairo b/src/tests/numbers/fixed_point/fp16x16_test.cairo index 1bfcd3d46..12f77e985 100644 --- a/src/tests/numbers/fixed_point/fp16x16_test.cairo +++ b/src/tests/numbers/fixed_point/fp16x16_test.cairo @@ -330,3 +330,10 @@ fn test_sinh() { let a = FixedTrait::from_unscaled_felt(1); assert(a.sinh().into() == 77016, 'invalid sinh of 1'); } + +#[test] +#[available_gas(10000000)] +fn test_tanh() { + let a = FixedTrait::from_unscaled_felt(1); + assert(a.tanh().into() == 49911, 'invalid tanh of 1'); +} \ No newline at end of file diff --git a/src/tests/numbers/fixed_point/fp8x23_test.cairo b/src/tests/numbers/fixed_point/fp8x23_test.cairo index bfd26c81a..b318d412b 100644 --- a/src/tests/numbers/fixed_point/fp8x23_test.cairo +++ b/src/tests/numbers/fixed_point/fp8x23_test.cairo @@ -329,4 +329,11 @@ fn test_gt() { fn test_sinh() { let a = FixedTrait::from_unscaled_felt(1); assert(a.sinh().into() == 9858301, 'invalid sinh of 1'); +} + +#[test] +#[available_gas(10000000)] +fn test_tanh() { + let a = FixedTrait::from_unscaled_felt(1); + assert(a.tanh().into() == 6388714, 'invalid tanh of 1'); } \ No newline at end of file diff --git a/src/tests/operators/tensor/math.cairo b/src/tests/operators/tensor/math.cairo index 74a629cde..922bd5344 100644 --- a/src/tests/operators/tensor/math.cairo +++ b/src/tests/operators/tensor/math.cairo @@ -15,3 +15,4 @@ mod ln; mod arithmetic; mod cumsum; mod sinh; +mod tanh; diff --git a/src/tests/operators/tensor/math/tanh.cairo b/src/tests/operators/tensor/math/tanh.cairo new file mode 100644 index 000000000..af6442507 --- /dev/null +++ b/src/tests/operators/tensor/math/tanh.cairo @@ -0,0 +1,3 @@ +mod tanh_u32_test; +mod tanh_i32_test; +mod tanh_fp_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/math/tanh/tanh_fp_test.cairo b/src/tests/operators/tensor/math/tanh/tanh_fp_test.cairo new file mode 100644 index 000000000..9ec10333f --- /dev/null +++ b/src/tests/operators/tensor/math/tanh/tanh_fp_test.cairo @@ -0,0 +1,2 @@ +mod tanh_fp8x23_test; +mod tanh_fp16x16_test; \ No newline at end of file diff --git a/src/tests/operators/tensor/math/tanh/tanh_fp_test/tanh_fp16x16_test.cairo b/src/tests/operators/tensor/math/tanh/tanh_fp_test/tanh_fp16x16_test.cairo new file mode 100644 index 000000000..e5cc62c8a --- /dev/null +++ b/src/tests/operators/tensor/math/tanh/tanh_fp_test/tanh_fp16x16_test.cairo @@ -0,0 +1,96 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 65211, 'result[3] = 0.99505...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp16x16::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_16x16::FP16x16Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.tanh().data; + + // let a0 = *result.at(0).mag.into(); + // a0.print(); + // let a1 = *result.at(1).mag.into(); + // a1.print(); + // let a2 = *result.at(2).mag.into(); + // a2.print(); + // let a3 = *result.at(3).mag.into(); + // a3.print(); + // let a4 = *result.at(4).mag.into(); + // a4.print(); + // let a5 = *result.at(5).mag.into(); + // a5.print(); + // let a6 = *result.at(6).mag.into(); + // a6.print(); + // let a7 = *result.at(7).mag.into(); + // a7.print(); + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 65211, 'result[3] = 0.99505...'); + assert((*result.at(4).mag).into() == 65492, 'result[4] = 0.99933...'); + assert((*result.at(5).mag).into() == 65530, 'result[5] = 0.99991...'); + assert((*result.at(6).mag).into() == 65535, 'result[6] = 0.99999...'); + assert((*result.at(7).mag).into() == 65535, 'result[7] = 0.99999...'); + } +} + diff --git a/src/tests/operators/tensor/math/tanh/tanh_fp_test/tanh_fp8x23_test.cairo b/src/tests/operators/tensor/math/tanh/tanh_fp_test/tanh_fp8x23_test.cairo new file mode 100644 index 000000000..cd5454742 --- /dev/null +++ b/src/tests/operators/tensor/math/tanh/tanh_fp_test/tanh_fp8x23_test.cairo @@ -0,0 +1,81 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_1x3_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let tensor = fp_tensor_1x3_helper(); + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 6388714, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 8086849, 'result[2] = 0.964028...'); + + } +} + +// ===== 2D ===== // + +#[cfg(test)] +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let tensor = fp_tensor_2x2_helper(); + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 6388714, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 8086849, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 8347124, 'result[3] = 0.99505...'); + } +} + +// ===== 3D ===== // + +#[cfg(test)] +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use debug::PrintTrait; + + + use orion::operators::tensor::implementations::impl_tensor_fp::Tensor_fp; + use orion::operators::tensor::core::{TensorTrait, }; + use orion::tests::helpers::tensor::fixed_point::fp8x23::fp_tensor_2x2x2_helper; + use orion::numbers::fixed_point::implementations::impl_8x23::FP8x23Impl; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let tensor = fp_tensor_2x2x2_helper(); + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 6388714, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 8086849, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 8347124, 'result[3] = 0.99505...'); + assert((*result.at(4).mag).into() == 8382981, 'result[4] = 0.99933...'); + assert((*result.at(5).mag).into() == 8387846, 'result[5] = 0.99991...'); + assert((*result.at(6).mag).into() == 8388504, 'result[6] = 0.99999...'); + assert((*result.at(7).mag).into() == 8388594, 'result[7] = 0.99999...'); + } +} + diff --git a/src/tests/operators/tensor/math/tanh/tanh_i32_test.cairo b/src/tests/operators/tensor/math/tanh/tanh_i32_test.cairo new file mode 100644 index 000000000..d16466b52 --- /dev/null +++ b/src/tests/operators/tensor/math/tanh/tanh_i32_test.cairo @@ -0,0 +1,113 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 65211, 'result[3] = 0.99505...'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 65211, 'result[3] = 0.99505...'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_i32::Tensor_i32; + use orion::numbers::signed_integer::{integer_trait::IntegerTrait, i32::i32}; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(IntegerTrait::new(0, false)); + data.append(IntegerTrait::new(1, false)); + data.append(IntegerTrait::new(2, false)); + data.append(IntegerTrait::new(3, false)); + data.append(IntegerTrait::new(4, false)); + data.append(IntegerTrait::new(5, false)); + data.append(IntegerTrait::new(6, false)); + data.append(IntegerTrait::new(7, false)); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 65211, 'result[3] = 0.99505...'); + assert((*result.at(4).mag).into() == 65492, 'result[4] = 0.99933...'); + assert((*result.at(5).mag).into() == 65530, 'result[5] = 0.99991...'); + assert((*result.at(6).mag).into() == 65535, 'result[6] = 0.99999...'); + assert((*result.at(7).mag).into() == 65535, 'result[7] = 0.99999...'); + } +} + diff --git a/src/tests/operators/tensor/math/tanh/tanh_u32_test.cairo b/src/tests/operators/tensor/math/tanh/tanh_u32_test.cairo new file mode 100644 index 000000000..4053d99e8 --- /dev/null +++ b/src/tests/operators/tensor/math/tanh/tanh_u32_test.cairo @@ -0,0 +1,110 @@ +// ===== 1D ===== // + +#[cfg(test)] +mod tensor_1D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(4); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 65211, 'result[3] = 0.99505...'); + } +} + +// ===== 2D ===== // + +mod tensor_2D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 65211, 'result[3] = 0.99505...'); + } +} +// // ===== 3D ===== // + +mod tensor_3D { + use array::SpanTrait; + use traits::Into; + use array::ArrayTrait; + + use orion::operators::tensor::implementations::impl_tensor_u32::Tensor_u32; + use orion::operators::tensor::core::{TensorTrait, Tensor, ExtraParams}; + + #[test] + #[available_gas(20000000)] + fn tensor_tanh_test() { + let mut sizes = ArrayTrait::new(); + sizes.append(2); + sizes.append(2); + sizes.append(2); + + let mut data = ArrayTrait::new(); + data.append(0); + data.append(1); + data.append(2); + data.append(3); + data.append(4); + data.append(5); + data.append(6); + data.append(7); + let extra = Option::::None(()); + let tensor = TensorTrait::::new(sizes.span(), data.span(), extra); + + let result = tensor.tanh().data; + + assert((*result.at(0).mag).into() == 0, 'result[0] = 0'); + assert((*result.at(1).mag).into() == 49911, 'result[1] = 0.761594...'); + assert((*result.at(2).mag).into() == 63178, 'result[2] = 0.964028...'); + assert((*result.at(3).mag).into() == 65211, 'result[3] = 0.99505...'); + assert((*result.at(4).mag).into() == 65492, 'result[4] = 0.99933...'); + assert((*result.at(5).mag).into() == 65530, 'result[5] = 0.99991...'); + assert((*result.at(6).mag).into() == 65535, 'result[6] = 0.99999...'); + assert((*result.at(7).mag).into() == 65535, 'result[7] = 0.99999...'); + } +} + From d09c8c9297ef1058742ee6fef073323687b2e57d Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 29 Jun 2023 08:16:32 +0300 Subject: [PATCH 065/126] update doc --- docs/SUMMARY.md | 1 + docs/apis/compatibility.md | 75 +++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index fa72c8f5f..12cc336b6 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -35,6 +35,7 @@ * [tensor.ceil](apis/operators/tensor/tensor.ceil.md) * [tensor.cumsum](apis/operators/tensor/tensor.cumsum.md) * [tensor.sinh](apis/operators/tensor/tensor.sinh.md) + * [tensor.cosh](apis/operators/tensor/tensor.cosh.md) * [Neural Network](apis/operators/neural-network/README.md) * [nn.relu](apis/operators/neural-network/nn.relu.md) * [nn.leaky\_relu](apis/operators/neural-network/nn.leaky\_relu.md) diff --git a/docs/apis/compatibility.md b/docs/apis/compatibility.md index ad2023954..fd22ff83e 100644 --- a/docs/apis/compatibility.md +++ b/docs/apis/compatibility.md @@ -4,44 +4,45 @@ To see the full list of available ONNX Operators refer to [this table](https://g You can see below the list of current supported ONNX Operators: -| Operator | Implemented | -| :--------------------------------------------------------: | :----------------: | -| [MatMul](operators/tensor/tensor.matmul.md) | :white_check_mark: | -| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white_check_mark: | -| [Add](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Sub](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Mul](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Div](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Equal](operators/tensor/tensor.eq.md) | :white_check_mark: | -| [Greater](operators/tensor/tensor.greater.md) | :white_check_mark: | -| [GreaterOrEqual](operators/tensor/tensor.greater_equal.md) | :white_check_mark: | -| [Less](operators/tensor/tensor.less.md) | :white_check_mark: | -| [LessOrEqual](operators/tensor/tensor.less_equal.md) | :white_check_mark: | -| [Abs](operators/tensor/tensor.abs.md) | :white_check_mark: | -| [Ceil](operators/tensor/tensor.ceil.md) | :white_check_mark: | -| [Exp](operators/tensor/tensor.exp.md) | :white_check_mark: | -| [Ln](operators/tensor/tensor.ln.md) | :white_check_mark: | -| [Reshape](operators/tensor/tensor.reshape.md) | :white_check_mark: | -| [Transpose](operators/tensor/tensor.transpose.md) | :white_check_mark: | -| [ArgMax](operators/tensor/tensor.argmax.md) | :white_check_mark: | -| [ArgMin](operators/tensor/tensor.argmin.md) | :white_check_mark: | -| [ReduceSum](operators/tensor/tensor.reduce_sum.md) | :white_check_mark: | -| [CumSum](operators/tensor/tensor.cumsum.md) | :white_check_mark: | -| [Relu](operators/neural-network/nn.relu.md) | :white_check_mark: | -| [LeakyRelu](operators/neural-network/nn.leaky_relu.md) | :white_check_mark: | -| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white_check_mark: | -| [Softmax](operators/neural-network/nn.softmax.md) | :white_check_mark: | -| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white_check_mark: | -| [Softsign](operators/neural-network/nn.softsign.md) | :white_check_mark: | -| [Softplus](operators/neural-network/nn.softplus.md) | :white_check_mark: | -| [Linear](operators/neural-network/nn.linear.md) | :white_check_mark: | -| [Sinh](operators/tensor/tensor.sinh.md) | :white_check_mark: | -| [Cosh](operators/tensor/tensor.cosh.md) | :white_check_mark: | +| Operator | Implemented | +| :---------------------------------------------------------: | :------------------: | +| [MatMul](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | +| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | +| [Add](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Sub](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Mul](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Div](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Equal](operators/tensor/tensor.eq.md) | :white\_check\_mark: | +| [Greater](operators/tensor/tensor.greater.md) | :white\_check\_mark: | +| [GreaterOrEqual](operators/tensor/tensor.greater\_equal.md) | :white\_check\_mark: | +| [Less](operators/tensor/tensor.less.md) | :white\_check\_mark: | +| [LessOrEqual](operators/tensor/tensor.less\_equal.md) | :white\_check\_mark: | +| [Abs](operators/tensor/tensor.abs.md) | :white\_check\_mark: | +| [Ceil](operators/tensor/tensor.ceil.md) | :white\_check\_mark: | +| [Exp](operators/tensor/tensor.exp.md) | :white\_check\_mark: | +| [Ln](operators/tensor/tensor.ln.md) | :white\_check\_mark: | +| [Reshape](operators/tensor/tensor.reshape.md) | :white\_check\_mark: | +| [Transpose](operators/tensor/tensor.transpose.md) | :white\_check\_mark: | +| [ArgMax](operators/tensor/tensor.argmax.md) | :white\_check\_mark: | +| [ArgMin](operators/tensor/tensor.argmin.md) | :white\_check\_mark: | +| [ReduceSum](operators/tensor/tensor.reduce\_sum.md) | :white\_check\_mark: | +| [CumSum](operators/tensor/tensor.cumsum.md) | :white\_check\_mark: | +| [Relu](operators/neural-network/nn.relu.md) | :white\_check\_mark: | +| [LeakyRelu](operators/neural-network/nn.leaky\_relu.md) | :white\_check\_mark: | +| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white\_check\_mark: | +| [Softmax](operators/neural-network/nn.softmax.md) | :white\_check\_mark: | +| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white\_check\_mark: | +| [Softsign](operators/neural-network/nn.softsign.md) | :white\_check\_mark: | +| [Softplus](operators/neural-network/nn.softplus.md) | :white\_check\_mark: | +| [Linear](operators/neural-network/nn.linear.md) | :white\_check\_mark: | +| [Sinh](operators/tensor/tensor.sinh.md) | :white\_check\_mark: | +| [Cosh](operators/tensor/tensor.cosh.md) | :white\_check\_mark: | + Performance optimizations: -| Optimization | Implemented | -| :----------------: | :----------------: | -| 8-bit quantization | :white_check_mark: | +| Optimization | Implemented | +| :----------------: | :------------------: | +| 8-bit quantization | :white\_check\_mark: | -Current Operators support: **29/156 (18%)** +Current Operators support: **28/156 (18%)** \ No newline at end of file From 04a84d0546ddef5de55106dffbe9d57dbb8439d8 Mon Sep 17 00:00:00 2001 From: raphaelDkhn Date: Thu, 29 Jun 2023 08:20:57 +0300 Subject: [PATCH 066/126] update doc --- docs/SUMMARY.md | 141 +++++++++++++++++++------------------ docs/apis/compatibility.md | 75 ++++++++++---------- 2 files changed, 109 insertions(+), 107 deletions(-) diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index aa261dae4..c39ebae72 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -2,82 +2,83 @@ ## 👋 Welcome -- [Orion](README.md) -- [Why Validity ML?](welcome/why-validity-ml.md) +* [Orion](README.md) +* [Why Validity ML?](welcome/why-validity-ml.md) ## 🧱 APIs -- [Get Started](apis/get-started.md) -- [Compatibility](apis/compatibility.md) -- [Operators](apis/operators/README.md) - - [Tensor](apis/operators/tensor/README.md) - - [tensor.new](apis/operators/tensor/tensor.new.md) - - [tensor.at](apis/operators/tensor/tensor.at.md) - - [tensor.min](apis/operators/tensor/tensor.min.md) - - [tensor.max](apis/operators/tensor/tensor.max.md) - - [tensor.stride](apis/operators/tensor/tensor.stride.md) - - [tensor.ravel_index](apis/operators/tensor/tensor.ravel_index.md) - - [tensor.unravel_index](apis/operators/tensor/tensor.unravel_index.md) - - [tensor.reshape](apis/operators/tensor/tensor.reshape.md) - - [tensor.transpose](apis/operators/tensor/tensor.transpose.md) - - [tensor.reduce_sum](apis/operators/tensor/tensor.reduce_sum.md) - - [tensor.argmax](apis/operators/tensor/tensor.argmax.md) - - [tensor.argmin](apis/operators/tensor/tensor.argmin.md) - - [tensor.matmul](apis/operators/tensor/tensor.matmul.md) - - [tensor.exp](apis/operators/tensor/tensor.exp.md) - - [tensor.ln](apis/operators/tensor/tensor.ln.md) - - [tensor.eq](apis/operators/tensor/tensor.eq.md) - - [tensor.greater](apis/operators/tensor/tensor.greater.md) - - [tensor.greater_equal](apis/operators/tensor/tensor.greater_equal.md) - - [tensor.less](apis/operators/tensor/tensor.less.md) - - [tensor.less_equal](apis/operators/tensor/tensor.less_equal.md) - - [tensor.abs](apis/operators/tensor/tensor.abs.md) - - [tensor.ceil](apis/operators/tensor/tensor.ceil.md) - - [tensor.cumsum](apis/operators/tensor/tensor.cumsum.md) - - [tensor.sinh](apis/operators/tensor/tensor.sinh.md) - - [tensor.tanh](apis/operators/tensor/tensor.tanh.md) - - [Neural Network](apis/operators/neural-network/README.md) - - [nn.relu](apis/operators/neural-network/nn.relu.md) - - [nn.leaky_relu](apis/operators/neural-network/nn.leaky_relu.md) - - [nn.sigmoid](apis/operators/neural-network/nn.sigmoid.md) - - [nn.softmax](apis/operators/neural-network/nn.softmax.md) - - [nn.logsoftmax](apis/operators/neural-network/nn.logsoftmax.md) - - [nn.softsign](apis/operators/neural-network/nn.softsign.md) - - [nn.softplus](apis/operators/neural-network/nn.softplus.md) - - [nn.linear](apis/operators/neural-network/nn.linear.md) -- [Numbers](apis/numbers/README.md) - - [Signed Integer](apis/numbers/signed-integer/README.md) - - [int.new](apis/numbers/signed-integer/int.new.md) - - [int.div_rem](apis/numbers/signed-integer/int.div_rem.md) - - [int.abs](apis/numbers/signed-integer/int.abs.md) - - [int.max](apis/numbers/signed-integer/int.max.md) - - [int.min](apis/numbers/signed-integer/int.min.md) - - [Fixed Point](apis/numbers/fixed-point/README.md) - - [fp.new](apis/numbers/fixed-point/fp.new.md) - - [fp.new_unscaled](apis/numbers/fixed-point/fp.new_unscaled.md) - - [fp.from_felt](apis/numbers/fixed-point/fp.from_felt.md) - - [fp.from_unscaled_felt](apis/numbers/fixed-point/fp.from_unscaled_felt.md) - - [fp.abs](apis/numbers/fixed-point/fp.abs.md) - - [fp.ceil](apis/numbers/fixed-point/fp.ceil.md) - - [fp.floor](apis/numbers/fixed-point/fp.floor.md) - - [fp.exp](apis/numbers/fixed-point/fp.exp.md) - - [fp.exp2](apis/numbers/fixed-point/fp.exp2.md) - - [fp.ln](apis/numbers/fixed-point/fp.ln.md) - - [fp.log2](apis/numbers/fixed-point/fp.log2.md) - - [fp.log10](apis/numbers/fixed-point/fp.log10.md) - - [fp.pow](apis/numbers/fixed-point/fp.pow.md) - - [fp.round](apis/numbers/fixed-point/fp.round.md) - - [fp.sqrt](apis/numbers/fixed-point/fp.sqrt.md) -- [Performance](apis/performance/README.md) - - [performance.quantize_linear](apis/performance/performance.quantize_linear.md) - - [performance.quantize_linear_from_fp](apis/performance/performance.quantize_linear_from_fp.md) +* [Get Started](apis/get-started.md) +* [Compatibility](apis/compatibility.md) +* [Operators](apis/operators/README.md) + * [Tensor](apis/operators/tensor/README.md) + * [tensor.new](apis/operators/tensor/tensor.new.md) + * [tensor.at](apis/operators/tensor/tensor.at.md) + * [tensor.min](apis/operators/tensor/tensor.min.md) + * [tensor.max](apis/operators/tensor/tensor.max.md) + * [tensor.stride](apis/operators/tensor/tensor.stride.md) + * [tensor.ravel\_index](apis/operators/tensor/tensor.ravel\_index.md) + * [tensor.unravel\_index](apis/operators/tensor/tensor.unravel\_index.md) + * [tensor.reshape](apis/operators/tensor/tensor.reshape.md) + * [tensor.transpose](apis/operators/tensor/tensor.transpose.md) + * [tensor.reduce\_sum](apis/operators/tensor/tensor.reduce\_sum.md) + * [tensor.argmax](apis/operators/tensor/tensor.argmax.md) + * [tensor.argmin](apis/operators/tensor/tensor.argmin.md) + * [tensor.matmul](apis/operators/tensor/tensor.matmul.md) + * [tensor.exp](apis/operators/tensor/tensor.exp.md) + * [tensor.ln](apis/operators/tensor/tensor.ln.md) + * [tensor.eq](apis/operators/tensor/tensor.eq.md) + * [tensor.greater](apis/operators/tensor/tensor.greater.md) + * [tensor.greater\_equal](apis/operators/tensor/tensor.greater\_equal.md) + * [tensor.less](apis/operators/tensor/tensor.less.md) + * [tensor.less\_equal](apis/operators/tensor/tensor.less\_equal.md) + * [tensor.abs](apis/operators/tensor/tensor.abs.md) + * [tensor.ceil](apis/operators/tensor/tensor.ceil.md) + * [tensor.cumsum](apis/operators/tensor/tensor.cumsum.md) + * [tensor.sinh](apis/operators/tensor/tensor.sinh.md) + * [tensor.cosh](apis/operators/tensor/tensor.cosh.md) + * [tensor.tanh](apis/operators/tensor/tensor.tanh.md) + * [Neural Network](apis/operators/neural-network/README.md) + * [nn.relu](apis/operators/neural-network/nn.relu.md) + * [nn.leaky\_relu](apis/operators/neural-network/nn.leaky\_relu.md) + * [nn.sigmoid](apis/operators/neural-network/nn.sigmoid.md) + * [nn.softmax](apis/operators/neural-network/nn.softmax.md) + * [nn.logsoftmax](apis/operators/neural-network/nn.logsoftmax.md) + * [nn.softsign](apis/operators/neural-network/nn.softsign.md) + * [nn.softplus](apis/operators/neural-network/nn.softplus.md) + * [nn.linear](apis/operators/neural-network/nn.linear.md) +* [Numbers](apis/numbers/README.md) + * [Signed Integer](apis/numbers/signed-integer/README.md) + * [int.new](apis/numbers/signed-integer/int.new.md) + * [int.div\_rem](apis/numbers/signed-integer/int.div\_rem.md) + * [int.abs](apis/numbers/signed-integer/int.abs.md) + * [int.max](apis/numbers/signed-integer/int.max.md) + * [int.min](apis/numbers/signed-integer/int.min.md) + * [Fixed Point](apis/numbers/fixed-point/README.md) + * [fp.new](apis/numbers/fixed-point/fp.new.md) + * [fp.new\_unscaled](apis/numbers/fixed-point/fp.new\_unscaled.md) + * [fp.from\_felt](apis/numbers/fixed-point/fp.from\_felt.md) + * [fp.from\_unscaled\_felt](apis/numbers/fixed-point/fp.from\_unscaled\_felt.md) + * [fp.abs](apis/numbers/fixed-point/fp.abs.md) + * [fp.ceil](apis/numbers/fixed-point/fp.ceil.md) + * [fp.floor](apis/numbers/fixed-point/fp.floor.md) + * [fp.exp](apis/numbers/fixed-point/fp.exp.md) + * [fp.exp2](apis/numbers/fixed-point/fp.exp2.md) + * [fp.ln](apis/numbers/fixed-point/fp.ln.md) + * [fp.log2](apis/numbers/fixed-point/fp.log2.md) + * [fp.log10](apis/numbers/fixed-point/fp.log10.md) + * [fp.pow](apis/numbers/fixed-point/fp.pow.md) + * [fp.round](apis/numbers/fixed-point/fp.round.md) + * [fp.sqrt](apis/numbers/fixed-point/fp.sqrt.md) +* [Performance](apis/performance/README.md) + * [performance.quantize\_linear](apis/performance/performance.quantize\_linear.md) + * [performance.quantize\_linear\_from\_fp](apis/performance/performance.quantize\_linear\_from\_fp.md) ## 💖 Community -- [Algorithms](community/algorithms.md) -- [Contribute](community/contribute.md) +* [Algorithms](community/algorithms.md) +* [Contribute](community/contribute.md) ## 📖 Resources -- [Tutorials](resources/tutorials/README.md) - - [MNIST Classification with Orion](resources/tutorials/mnist-classification-with-orion.md) +* [Tutorials](resources/tutorials/README.md) + * [MNIST Classification with Orion](resources/tutorials/mnist-classification-with-orion.md) diff --git a/docs/apis/compatibility.md b/docs/apis/compatibility.md index e51a2bbe3..a3e457040 100644 --- a/docs/apis/compatibility.md +++ b/docs/apis/compatibility.md @@ -4,44 +4,45 @@ To see the full list of available ONNX Operators refer to [this table](https://g You can see below the list of current supported ONNX Operators: -| Operator | Implemented | -| :--------------------------------------------------------: | :----------------: | -| [MatMul](operators/tensor/tensor.matmul.md) | :white_check_mark: | -| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white_check_mark: | -| [Add](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Sub](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Mul](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Div](operators/tensor/#arithmetic-operations) | :white_check_mark: | -| [Equal](operators/tensor/tensor.eq.md) | :white_check_mark: | -| [Greater](operators/tensor/tensor.greater.md) | :white_check_mark: | -| [GreaterOrEqual](operators/tensor/tensor.greater_equal.md) | :white_check_mark: | -| [Less](operators/tensor/tensor.less.md) | :white_check_mark: | -| [LessOrEqual](operators/tensor/tensor.less_equal.md) | :white_check_mark: | -| [Abs](operators/tensor/tensor.abs.md) | :white_check_mark: | -| [Ceil](operators/tensor/tensor.ceil.md) | :white_check_mark: | -| [Exp](operators/tensor/tensor.exp.md) | :white_check_mark: | -| [Ln](operators/tensor/tensor.ln.md) | :white_check_mark: | -| [Reshape](operators/tensor/tensor.reshape.md) | :white_check_mark: | -| [Transpose](operators/tensor/tensor.transpose.md) | :white_check_mark: | -| [ArgMax](operators/tensor/tensor.argmax.md) | :white_check_mark: | -| [ArgMin](operators/tensor/tensor.argmin.md) | :white_check_mark: | -| [ReduceSum](operators/tensor/tensor.reduce_sum.md) | :white_check_mark: | -| [CumSum](operators/tensor/tensor.cumsum.md) | :white_check_mark: | -| [Relu](operators/neural-network/nn.relu.md) | :white_check_mark: | -| [LeakyRelu](operators/neural-network/nn.leaky_relu.md) | :white_check_mark: | -| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white_check_mark: | -| [Softmax](operators/neural-network/nn.softmax.md) | :white_check_mark: | -| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white_check_mark: | -| [Softsign](operators/neural-network/nn.softsign.md) | :white_check_mark: | -| [Softplus](operators/neural-network/nn.softplus.md) | :white_check_mark: | -| [Linear](operators/neural-network/nn.linear.md) | :white_check_mark: | -| [Sinh](operators/tensor/tensor.sinh.md) | :white_check_mark: | -| [Tanh](operators/tensor/tensor.tanh.md) | :white_check_mark: | +| Operator | Implemented | +| :---------------------------------------------------------: | :------------------: | +| [MatMul](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | +| [MatMulInteger](operators/tensor/tensor.matmul.md) | :white\_check\_mark: | +| [Add](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Sub](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Mul](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Div](operators/tensor/#arithmetic-operations) | :white\_check\_mark: | +| [Equal](operators/tensor/tensor.eq.md) | :white\_check\_mark: | +| [Greater](operators/tensor/tensor.greater.md) | :white\_check\_mark: | +| [GreaterOrEqual](operators/tensor/tensor.greater\_equal.md) | :white\_check\_mark: | +| [Less](operators/tensor/tensor.less.md) | :white\_check\_mark: | +| [LessOrEqual](operators/tensor/tensor.less\_equal.md) | :white\_check\_mark: | +| [Abs](operators/tensor/tensor.abs.md) | :white\_check\_mark: | +| [Ceil](operators/tensor/tensor.ceil.md) | :white\_check\_mark: | +| [Exp](operators/tensor/tensor.exp.md) | :white\_check\_mark: | +| [Ln](operators/tensor/tensor.ln.md) | :white\_check\_mark: | +| [Reshape](operators/tensor/tensor.reshape.md) | :white\_check\_mark: | +| [Transpose](operators/tensor/tensor.transpose.md) | :white\_check\_mark: | +| [ArgMax](operators/tensor/tensor.argmax.md) | :white\_check\_mark: | +| [ArgMin](operators/tensor/tensor.argmin.md) | :white\_check\_mark: | +| [ReduceSum](operators/tensor/tensor.reduce\_sum.md) | :white\_check\_mark: | +| [CumSum](operators/tensor/tensor.cumsum.md) | :white\_check\_mark: | +| [Relu](operators/neural-network/nn.relu.md) | :white\_check\_mark: | +| [LeakyRelu](operators/neural-network/nn.leaky\_relu.md) | :white\_check\_mark: | +| [Sigmoid](operators/neural-network/nn.sigmoid.md) | :white\_check\_mark: | +| [Softmax](operators/neural-network/nn.softmax.md) | :white\_check\_mark: | +| [LogSoftmax](operators/neural-network/nn.logsoftmax.md) | :white\_check\_mark: | +| [Softsign](operators/neural-network/nn.softsign.md) | :white\_check\_mark: | +| [Softplus](operators/neural-network/nn.softplus.md) | :white\_check\_mark: | +| [Linear](operators/neural-network/nn.linear.md) | :white\_check\_mark: | +| [Sinh](operators/tensor/tensor.sinh.md) | :white\_check\_mark: | +| [Cosh](operators/tensor/tensor.cosh.md) | :white\_check\_mark: | +| [Tanh](operators/tensor/tensor.tanh.md) | :white\_check\_mark: | Performance optimizations: -| Optimization | Implemented | -| :----------------: | :----------------: | -| 8-bit quantization | :white_check_mark: | +| Optimization | Implemented | +| :----------------: | :------------------: | +| 8-bit quantization | :white\_check\_mark: | -Current Operators support: **29/156 (19%)** +Current Operators support: **30/156 (19%)** \ No newline at end of file From 3bd386d8c2c25d243d2d0c81d742af5f8484c68d Mon Sep 17 00:00:00 2001 From: Raphael Doukhan Date: Thu, 29 Jun 2023 06:05:22 +0000 Subject: [PATCH 067/126] GITBOOK-11: Orion Contribution Tutorial + Guideline --- docs/.gitbook/assets/article_header_ORION.png | Bin 0 -> 5238921 bytes docs/SUMMARY.md | 1 + docs/apis/get-started.md | 12 +- docs/community/contribute.md | 86 ++--- docs/resources/tutorials/README.md | 6 + .../implement-new-operators-in-orion.md | 353 ++++++++++++++++++ 6 files changed, 399 insertions(+), 59 deletions(-) create mode 100644 docs/.gitbook/assets/article_header_ORION.png create mode 100644 docs/resources/tutorials/implement-new-operators-in-orion.md diff --git a/docs/.gitbook/assets/article_header_ORION.png b/docs/.gitbook/assets/article_header_ORION.png new file mode 100644 index 0000000000000000000000000000000000000000..c5435f031196501012fbe04396c3760b828a0b08 GIT binary patch literal 5238921 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%0A8UViuPqG@<#x1De=9!y6Gc?# z9=;XJiKPcnV`M&pSENgsnmHh=nS*%t*Yd^($TXFcY| z7(Yw(cRZcO$0{ep;aJtG#fzbOCQc8*JTxDTx0et*;E zo@J{{`BUE>{qsZup75uS#Iu<4q_h&wFf09cWXj|^J>wqPH}xd;m;13Z3fuX2kOck! zrF9cJ#PC-7uGL)^1f|6F;wcT-B@j-tJKdi>yqyyl2X6tHtpQZEI}g#|mPM#|hu)3y zidHdwo{jlFwO>6FIL=Bkv&yCKMwnlQP>D|^zY0=5_&HLr{8|HMEdG2XN%RqeE$cv( z&8YjnRIBy4v=WEqJ9iEsC4NxGs9fs}$MpA$D8Kt{-bL%xe(dP$F0dju3IO?d{Ywn$ zgE}#1N=V#B@b(J)00a5}9186YUEWIjm||rGaV#KcT|3T# z6a(B%1Y@F`%B(ojRqAm42XGQzs{qj6e~J9SIUK`h35SXWbkHzh6i54O@&4bi3|jEN zyN{t(F+TZKS_yw97AUsdIX9_Xn#bhr(rj7;4GW;>MJc4Wrz)cHwo;qj&SP~W%*SXI ztHTuT`n7>DlYS)_ll||VE-K3d8fxFJKR;@`r+z^q&=WylseX1Q`E4+lqOsmfI<1=q zv`?)MxH$B@w;{y4qy)&MTAlAZI;gh}`$g7`w`e~aja|{Jy@lFWB4aa_lnPwpAAc$8#6lnG=yB&u zNppN0Ig0UbD|IEwlYmG2Sy^Vt6theeyAn2Pdt2~lu zGMl!+yME7q>D;s!iz^$z3ykDkkZm3fi_u3VBM=p?D}^1T2;Zi$&Ownits9)stnbg9 z7CPSL*NG*o%mSzg-C17!XL@UmIhnc2Sbk2sQ7&2aj#Y1u2I`3ODLju0rZK2znU8o7 z&CpO%6X<;IvOoI9x9G2YPyELe`>A&oJlPIgYBTYB#o3Yn3Jot$y3&83i+qlx^(>4i zPkldlD1j~`Btyiji~E~CDkQc2S+aB`mKg&unzpn;X`$QADdjF)vETB)wURxbqj=45 zWlr`v*^zik5jrm*D`1tWN%~HvPihjbtWG_8cBuh*Gap>)1KbW&qjD?!2v~$7P#3CJ zC(R_?bM9txX59BqHDi|~Z`4pf=R%wBkpVaPl0AC0CWVEP^2&i$aMA2`t&n>5902R{Q_zBkNR}Oj= z94h=Z8zInlJV$)*{*C&-M?W5(R?cCS9%0p8v*rH2+*T-n4KdIP_jWzlKO@Ap3vlJ^ z{mnlCc~>{s_}IJ1Z1e#6C(k7VTyqwc&_dKjCT^Kty zGNuMySFf;w8>;A;N4{$pO#P6TmiRdKnUj=RZm5-__*8u*$0d9yFG?eUOJ>w*@!kHG z#Pb<#M(|uj=Q`nBSqqpc+L!j^Ky2vq=~=jcv(kq-3F2^Pw{4l3fPgbiM65L{eZ^Qg z~^Red<8+Ph)d zLOMmXUZ)LZ*z2tkpLX4&GqUo{io_;5gYILO8iua>g>y@XvlvYKEy**oqEXO>w(4{! zg&+BQn0y6+@07vqx6mG7E=eRe*3P^>aUSfG`He*|ki5j`Dr7{g^Pr(hco1zM&Vg|NAb;)_M?WN z!%4d$%E!f3AcbBB<3|rIW9vehl9ni=2fInv>B}oecSgf`EY#-ir2l#G)NPYXP#jrs zQkgsc`1DJ$!rQlB&(^lYjz`TTpX!J%Xn`BqM=x^(OkW>0VOxdjCY1{x!pkZ>3t2pW zs(9bGoghsavD8%%;FPi!W!0GMGW`B1)_AX$2pfn)!aV-%Kzy5OwJ6H@1Xttj*lZ*K zFuB?5bfgrJFCPS2cZ7c1sdp)&gH*d?wMjp*zJq&jLqnWN0k(Sg%(OFMJxSB^bV5r+g26JM_KPzo(a0sD1wSuVl1|ddult7+1nHd#W@Wrh)`Bc1*Fvs6C|>tDnVwhf9!{s?=n( zg`K>SZ3`C=bpC*^Lo5|WsNr1uZqP3Jdg2&*ZST8e`kV?v%PO{OY5EFtv}x7{&~p#k zIKBBXwQObi*vW)kF*ZUO&+ZWXq)}Q(^7vRW==PZKm;y{2fbpz5&c0}yZFM@k%%EAl z_S}G8O&@3bi5(}-O|PYjoPgW3QY)Gd#2*4k%TM3VZnaf8;ZX$`yi=AHT6509bQU?Rbnz&bYJMe!rzKRhr1P{7VzEjY!&Of4d|r z^pA$)RtGvjBHH0XpnjvVd8(}}@-+x$n9M=6VCurpUuCV()Z`Jn8)PXm#dun$ZXSRqqPYqOG9LrOH6eH+4 z(b@$&BAzSUL_@M4tNk{Pjtgv;K5vz@=b^Unn?cFw%}_W>N2kO2laqWW0`nI)j*;4K zDH-xyNjGiMa)B;h^{yPQ_DUnTgC%X#3`+MJt@CV(d$wg%Jw-a@RTBz4IwtkWNSx%r zn`3_~cjXY?E>^DKVRw}TQF2gCQpqmTMb`UahC^sQD3IDAQ(xJ^bdP4<;w3Ojp$MI-iZ}U6G5y#HdLqvtCudpHH_Pxyk#-UPMUVs5 zZ10WNakWN%lFU8j)g->aZqb@0MZ2Ky^e@KPrWN1%INGIToUv->%f+lP$`--lo3ZX8 zBfW}C>N^*mCpx!(_f?vHX7;k1C300RTc9qu`~Jkk1CVFTPK|qM+AXjTwzyh~Ub7S8 z_X7A&fKkL}6awY4S}VzWCTaY3W!IYvX6dB>&v%aYa(?YGckl=>-zgQPfM+jTE@hvg z`~u4C_l4ixWOy*OAH%a@Q3yKOYO_0XE&Y@h1V4Q{=E#cl*6RX2p2q*4vD# zmw;LOVB#mOWMOtLG8z-Ockf@v?t=GLtOq!UB}PVm={OW$xog9rAgMl~j<&Q_nhy^~ zXPIc@r^fU(F~$`lq)Qn<;Km!{sFaTl(6i`AphZXW!Mbx_i@Sj@6Zd!N8aNVV@~$qk z>kAE+=(1|p11d=OYZm12>QB|1$L<^7*$UZWNJ(ds4eqBS!`8ceky#99@ei<`WR}hM zbbTwBjGxM#Iacm+@Cp%=9jdc17b-IM{T&T;u`zO*#=c;AE3~r1?@CpZP2TV(qje1l zlXH~Hi9MVcM@RkLA0vOK+CLLW^@8O4oZ;pAX3JAN`(b}%+=+Wo2<-Uep%a6@9V>n7 z_;i!mKT40-Iu3aBERU4Sv{gEI;SMv{U(sC4>gnlAb{f7gT|(2jb$O_we2L$-hqG%L z&GR8(mxRcrZ7z>|#$dkjyUsA1Ris9>dL1Vb;^~1z&m6vZUlfRRy2>hWE*|wQW(4UO z*~h`r6Ob*c`CeL>kFepe%EM&vc06-&^H@tC5<))TAn#iEz9Dr*=CS_g)4RcEAgIiO z#|*8{_Umly zkulkWB|3daYxduCi4ox)(a=G7HkCk@%Th=9^Ee{H>T=!%kmX zd}`mTmoJ>Oao+T8kFj+8Zd+^tOt0-~Pr%aLf_byvvg+NL{r}PQmSIi)kNYL|d_AZvu%uQw{s<7J`J{aX{{qjOI-N0fU^vjn zqmM$E&l*J;gO1a*MbI`HxeoS{2SGnXG+Bs=Tqmthu}^sLV(6+43)1v`zrc~*8%$SI^@)eke9E03KXk+vZ%L6h{wKRJ@4 zPdRaqge$H}dm{>VmF6H)y^{kvH(iU!4umko*r> z;Yt+w?XsU4EYLG3!Tk5qu)AGj>ht3r4a}D<$IN+VR!fYsWAVKoou^jK(sZ1WbPQkK zZcA^qH;e*fGfo!YC2UjdS%U?nbrmoH9|J$`eJ`gTb)AHV*S%K|Vz$5Q4t3+P_DR~D zd5782^lc>mSppv(Z~j3yG6m0Y)~B;*y4M@jOUQGdEwkzrurLp4yg9OF+l;j zYk-95touFI2jM~J9UG|JMb!)MbudZbdVy8PiK$iRf94sC9RsM8qn##;)87 zog^MRdV~3R1x!(z*;rKw1(FBy|9`S`%xu9u2F6|wPyjx<2|R!DkK;e`5LQ3}h&Ku@ z%(JU+WCoi5dmQjTtTT)nvtPiD)$V>&?6GW#26zXN(_;a8Eg{9sy! zfcB_g)~19Xn}!Y|zlOe3j8-L|`?Jx52pn96B>I$pcr_n%!*;=VQ@OeCzGHTMd%=Av zY7_Gk2YFjjGm>QXr{y{Cx10DvD~1}YpipV(-{A}uIbA>);4@DJdrSB{{P^U!5F_kb zniP4U(b}9CVIryT3|ml6_HE=Kex}~pz%61`72fmOY5W+zg&vK(Gnz|Iv2R#BxaFN! z!_gThqV9(@oi0|P*7W^s9Yw@!Pyg_7nK4wX&~hrPOi@@It?;SaB)0l{*=*`f?&uHE1k~b zkTIN%$HVI<>YVfQU8NMJm|~3%Xit&%!M*hjdT*c=8z$TdWgLTd+V~Teuut0k5~Yx?58C_+zXMuZ)|79^awD17VvS>X}gtzr)MOhC2q7 zhJ>V_-LZ&nEKitjzwdz%i=6PuJsEnz9+Bh-lV+Ctq2V(76Djp;Bj^{0x~$?Yqx4G9 zP0rm{0Nx**@(YoUnnF8EwoDsz=TXIqI-Uj`Z3_@ivtvR}S!Et@icCMFkAAbHv`x4R z>&cC@u!e^s7#@&=UE9Qcin!UfH|;m=#2h;4 zv_1$ztwYv0u&LDn<;tDcO*Yq)&R+e#E9bJoA)9W?oRU+gNnJ{g3VK(@7}tEfU=*i% zpbUonCj1a`O3*D~+A;z_8xc@{==przqhsSQ9g@s0xt6s|#DBqss4c>pBz%JCZ_*An z>o$GI%}n1t8c&1MHynEzV83N*BE#5ZA` z>@0M!FOCYx)l|;jCjsdrHzfmg=zUJDL*tnMdtcYXG8{-+TBmbXd>8Jf7c5n5$xzauX)n+{{h zDgDx}!)nn9*2F_pC=H7z0j%dSCgoBallP4V$Wg) zw|)XttzWGupxQDb>*f15;%aaimM33txzuo>kRcSw8L$bVpx~!aDZ+2>J_mNDf z{&n8vbS@L{1+8`K+OCEqxJ2{M2)pjY55$W9I{O4|oy@jFHtuR*s+iD@$f-g)FgA;C>XS0TUn1S!i-_dYLtV}N>_FdGo7yD?t=N5aY@B=yWKfFUfAgM~ z+cdt$FvHv5(Ha_wbT*}#_R_OYjdViZmUV+i)OYw1VODrD_kpR#HALLS6Vz-4`A7K7$(b6(bw?iR6dZuI>sYnF30Sw018I8g zwgUm<>14t{F2t8{yurn+hXi)jD{<(6Wpc5QY!;+jA@|2-tjIFM-}KiBZ#-ZJMWDU{ zV_xnP;^1BUlZQgKM8(*Tq@sV5<8@jm(l&y8a{Pzq$(IYwy2(wvkFnJ;xR=_0o--tj z{2A=vYrhnKY@G0oJ_h`^uc9xL=uM#0%r1!m5xo84+lH!hvx-ni(3RZDFLFi5+;#h? zy6{gYmM?Y#MlZw&wP(xr{Z~JWk{I7vJ)|tBF` z)rTA1db8vp8BiN}Ul*ModP>Bk(DnalAfGdx)!QGDk#6)>gnH^%mKWYJ5W?1}f5!yx1i^SirIcd#phc z4o&w`Eqc9ifNpbFzUu8A^Hp2uZcyHt%;AjWLxC7)1z%2hV|;-0$x~K#8}WA0IX32i ztM@wN+S{7SLx6utdR%fEkNGEliRJT%$U2gkdG(VhRcOHVGA8Twfn9{s+XnlL3o!dm zoVV=7*Aw-kQaJw*4^?cF#Xq)vwm#m4n0LqfCf~*WJc__G{N3#Bcy1>tC~Dbe{3;6R zJ+OsVYAGuCW4UBi$;!_6kk82*y?W&AGkyDaHS5h7q=>iv>J_&_prUZ0xPD9R^9@Sd zvH(i2sUe#U1{ROgs!h`?lTPo{}O8;d&`&?bYaAVg3Ud~#3berezaq} zEW@YeUzF5$=YxYzZE8B=W&H0B?KCHM9(keHLcNi(nUD)3+@9|g-g@Kb1edb=Z+lIwQclSuVrsdP*%jZ$n;^)nu<>DbCxu*^yCj~muvneL^{EE9p zoHx2fCujmze8ldDQoVj9`7GM37#>2p^0D~Oc2`Iy06RaMW*g7w6 z6>R_Dt-;%InwC5uzGS&N^-=oq^I_*Kvn>>?J--u@4#a}g$qPH*GPg~8t=GO+vc@#g zd_W#Itr@QwUYovIq4hf;5(={Ne7w4~njpvV@NbWlN6I88n!S-X zrnR}Lp&j^`_}fE{(2_U^k1F@>}rHE&Dr{|swIlw zDM!e%cDiN{&Gb)mYW72=*#i}9jQKWG>Wc;yL+4s3Xr?>Jb&!4*L5J64ceGLi1l?bb z?`$=jf-bxoNV|PYfw9nc>|a?Qs1k1?MZ3aSBS35?Od0|Xg^8kZOA}RVYW}+T^H?+>Qp9{ zo&3>DShbk;Cn}kbgaqu){R~uDioTt<p=G6a=qEj zxGV6yvC<%rn+A`U5VntrZVd|<5L7e;9nX;spVcP9dn@2vfmCx2b* zWYIPd75)PM&RhxD-y(~|pO0qiS2b!>5;6&z3)};Wr&z=qZ@=($;=(%AoF^7CkChVN z;expRr&(N%zN-BGW&RtPi}&Ix!dQ+26Bm+m9;)V5?X~HHfN^Q7z%cVUhtJGK_ogG5 zh^(@;d8((yTA=2a7iZASs^4U$Q$Z1q(-DB%mocm1tdoES*bjr)!dxY25#DR`VkDlQ zvs7E}jSdo(HsT!2bFl{al;Z80i=O5 z7WYVji4&Nq=xa9o0Uy1e_pk5G+M78>o7 z{c3)YGmtCRn3XU;9^ommVivq%2pqTx#iA%W8~b10BEth5-3Rq|T)mHCVUJ9MiU+F6 zftq8$1BZ8iyX3H=ekyy?7?f3CYF=0SBK)sMPw zU0<>|JnJpp0<+;%1K6O*_WkO|_ekcp4ZPza9J)`j4~ki$0u;t=jaF3 z#AXhYtMV+vK@nX@O?Vve9L?5&)oK`jXP-bX0^2>G@8$N!z+3s;MpWJmc4+Ymgu-KS z3YB)!jT`$^PlKOj9?%l7)*qcXL`H-ULJkL-7&tyH)_M;76*I!=2`NXYG?m@2*Fl5u zj%HK`;Rb474&Hvq+i)s$JkZ$lLlHj|$MkkJHX?KV$*1Ct6L^k73qD3ixj)U+IJ4L+ z`P#v+&!QMNW;-UV1?zv{L5&Fv*f4mz6U$TjG7=$=kKHWDa{b`qQ_7Rr1W)CYz9Qnd z`4ib{NJIx64qB++JWn1$k5Km%qnv|eEvto3HF#p&R&k6NBi}3gE3 zj8+Md0pA(=Ac&pymMas`J^*%(=oD8T8CorJ50zsr0PS6`iEPRic_wvWUyonsgp z@a?h_JbS@1)llcd? zu2c=gD{SN3{cZkAS)-=RO%y=x-gm|c1scWB;YteK5Pi&QsBPf#FCR1~ddpTES+q@V z^XhjffqpMU6mz)Ji!aXHjh2z2MW5dB>vrOstDWB1#~cUQL+v$*02A#mbVK@YNC1~} zZKsji24=R%+YNVbxv!S`rvVHfvfZbW+Z306)YX$Al<_m&NC9(}N4w%NVgG_slLoZS zH*GAP82K*6z(_y-=Q*bk6xN_J@mwy)(B(=rkzW^SR76ykgsibsVA%8L-{a34ou|ad z{nDqWu+sDx$(&%vxI3^YO@XIRz&jhxzK`PD515N;6EMkuPDsM5y1y2!iuGI!R1?BArC;@em~hqEHk8B!h!Ar_}8l%G6;<0tf8HM zzblFP2l??%|E?ff#+5k>j!s<53jw%^mdhrJ|A_GjIL(EXxD}r9GK}yUT*9^;sQ`r+YQ$p9{_;{_IAaVhm1Y;vbcTu*I;`H7YZ;W$v@^*SeNl z`;Itzs3Z$FTA%7Zc6G7sAW!)_y^vjFFRAQCFwdb#wz`J7F=eW}wC@XCc;ym3#G5MC zM#^r_4FkF}^MCxaWMsAF5+C-2MRrdf{-qZ?r$Bg)1B~QsH2bR!N*^j0e#!u;*AixS zP|Gv!Ml2|hat#Pgd<#*EB^#2(f^8mPCJSWq9sbLTU|UkBU|aWfh}s48D?o=}J!>oA zgDF~7BA^MQs|*q)|5u{|3y;K87cc;zz)DmbI3(yqZnzSfh!+WL@#(AtB)kObhyQ!E z)XM*Jc7Xre$TE}56L`z{_Fr( zOQvQ(H6ufF^Am|E=WgOw+1T;7Eexm(6oi8s9l7nb;Qc}2(em*Mm@zMTKys@BMf zFkqYx4WJ1!ns?5%F}`cJ%M*n5n>*y|d#_mmeuL@sZ39$?ix+3f^d+r|{q>)`8fqOh8^X?y zrp2*rau0lIOmN^Jk*_pvRbU#x>!Tt8`OOXSE%ce+7`o6MMd&peFfB>TG|@AbB~4){ zFfF}b>Q_U-Ue|$HUdDJ$tOaC1DapRy24;wsIQkdQaW~{H)pf?4sNPi9f~NI5W7{zQ z5Ex!yF?#nL<6jjrbboz9X$^A1dyzx-&}rK~A?jC%#I)LN5k*~9!&e{AjeeXS>XlwlbF}t=B@SF z*YC%I*2~XiT~@ks(rq0T$bMnyb#$Zz^}iwcx$gOcm<<G_>@#V85`ghNIn%Gq7?Ypvs(p|}9PdNpF9AU3ubrY2&X@Gv4sLjh-(Lg<$dsRNf7+7cO%BF-bG@ zC>2GY4G5ZWQsRw`inP#u<~Fq44(@-^xlbR92BYuTXyfxgD2F_#v~O6qMi>m25jtd> z=!*6DN@6fYmelpBh)iikU@37>elTE|PxR&8V(9eRzt^D%-jOGUM;?zewd~rBcdJ&D zK48BMV=^ouqSaCgthEn&WV%(A9&deQkf?i3+Z?op2JL8m3eZRRXJdR=s4-{r7yQSx z8ZzTK9Y&^rw|>c+oh-YvKgC9dZ!v;s5IjE9ic{i)n03OLW)rq;(SbyuCMHGhY4F?B zxwdklkUIw zw*K-R;$suXWCiW&*N~V8V|m2K=%EJ?3&L}YCU>#@1&adIoe|^9TWa)KO`q2rrI_+} zmf;U~^x-m6fitQR*swH)#GOQhu{ zFP#Gq^UIUm1{IS09(^Lx9?0&x=f5zZ^;VpaC6BT3qICdC&{(zKbc`5z@X_A--LbWD zu-!ves=C&aDJ)*`qqFVQs)~gw(Gy1$$b{K+;`C`@ud_mt@OM|gLxpylYGH}Dq&B{h z!(VkU9FzVSZ!|GOq88j6ECI#ZgZxwJ^x0E6AG(p|UR z1lluqe8%ZF`_xg1Z6$+Z>xMK>##esV?OOUP;nNQF@==)#J4)fYA52JFrwNsj!+dcNb z6TbfgU2`~Zu<&fE&qnmmvcz(Q!p5nTdz}%xQ^|EiD&Z`^O5PuR&fmUtRnNb|%Ix{R z$Uh%}J}$mOuinrctWbxl=3otyg}|c|8Lxq5=!U#P3qq1s>8=T!QTGMe13va&hYXWq z{S&UDrj}E1&TS94;C7V;sFBh^1AqrK2WCqqk)W_gxC(0jAA>j?nC@TY!xXGYd1H>6 zyaNuaoW$3rc~R^BU7A7h|7kT?+hq$lI|v7aum7`p60?hU{eN8ty8ma$0Od@7GeeG0 z9gG*px%OgngFzh(^jDf8n8*djW9^NT20|}i#)`P@izC$0T{^F}kV#9pChNGBskFI{-}xqU1Mjb`M#rPXRJnPP zz@PSvwwIvUAGxOU;Z~xEIiZaYf6@3tw;wwq1EQ{Ta|x46B}3*fbGb^kFiwjbbyRdg z7ZHIlK=QtnqB|oJAX@)qbc=*AlNUyA$1(I;R4%>$ltU(_*I^dKKH9R}G35K{@oLhM zT;EpE&qCI1;-RCc5ZK67{FyQE^{J z;?LgOB^l&+A5?OO#5p(^%T@v&O2+0Dhu0Ff1252K!x^pYnsyF?4w^p#p-q&UZHg9ojeJUw0sFH1*IYIR{Spn**~`p#_Q4$nX3l(g zPxk3z^xo8iSWAd8=|17lX+CZ7W_;UHRm+^K1hRO3I>J3b&X8!}mE1rb&qoCPgGxGM z>?y-5M;0k7;DxLua#FtD_>Wf7ctwAO3eyBvQj}>6fi! zj?WGYqjRsr<%!V8sK^yL6kTsv5=GCOxVkYp(!FV@u>T6*bZpDN;)>%3Vx^?7BF0O5 zSqg6C9z+w;zF~1rou%dZ`C)A_BK%&L`&SkH*Jd*1Jzhhq4ln+V%xR%_8eBu0*X1Cj z_umigG7Sm;DJN$KdP!w5i65S>39^1}!r8ob2(_?{AkhBHkF)iNp#Lz~pjzIgjpASu z&uNz;km9T2F5R=IL?dnx_aoOu+4188|A7@KAD#lPu&PXwhX@=T|nhO%0{z8CP+)hMx5_lzNg z2RFRq=RBjtf^+hA|4yIuuf@gZvmv%8fy_oUe$*cP1_!t`HbjkjXHUVc?xO}3UiD8~ zE`;7JjWra8C!K|pQ~wh?A>VjF^rQ!-%7;T$@fallaJ}B9$iV)$g1qOH7C}#~mH_t+ zPqBv@2W1pxnbAeM6ws#9m~RvGG9S^IXb^AI0M+mN7;`qB@4|Ghc?zs| z<~F=5)}O`M2A&?nOM?XbgUP1JS2U#}k6B8#lr1qt&%WdhQb*2LuY+z@0 z4`VuPsoExv#{+coklL&fN{1|V#1+t^jqm4JkQH-*L*d>omOmh1V;Y3duMS9V z^Whe@_xUvbyULIuorHe*%6IYVU8{S-c5WF7Ql(o!luRi5+Zo=Ao>@tg;?ss)DRc9F zQ#K=S7@r*@(c8~fvEvH3`1$?;3&sq=EI{;yM**G=hxD87QQ zc2dRhH;opPaUh>WBZ8cf=}=l%!-0XhNgrBWjWp~kv*B+uy8QkQLMyj2CiQSu`e z5YN<&@u)WE?cdc$JHGT=@u-!J}FR$lc{8_FC9^_)liU9D=GP5!P}7J!-K|4 zdr^g1Wr9V>yiIz%IbPj}3RnX%XTsCB%~3L-N;#dPmN^F&8gJXUKj8_f!C1~+U%2%p z2f8g!GW6+w*m|aNW*J%JLE1(Lws51mv08!@9dG^!!DQB;UC?J15`9i@V$fI!#W#SB z$4K(`s1HQzE0a@Slm19nS?*EKitxj72)3J{J@oW;yja4p0~^v6b4ngnPq#LV|^-v zsk;S7^_Q>fgKK^vt#a{hNsF_0mn^PV?Oq;gpyf+OG}^USI^`6PUCYnj4rB9E`6{15 zIk~FB#70UO&FL2y+jdFUgZYZjwDss@O+k+bVH?7q`8fc4Mcvru+)%`!7tyKg0O**{ z;_Hd?*jw78S$gNz>qpt|IRFaEgfp-{N++;l`I@3+(6QmoCiocPi8BVX;JSW&C-jMJ z`=oh?aCns%05B(DZgF(mu`^;dndP|1g43$^LT;?Ck++~=c5*6t%KaazKRensts%g{pvCP~FpA4v&R3ri8 zeKm7?nMq@M#~oyYx(fPFq0tmCt;UXQm7hVb+OW=7frpy$|D>Rk0t>zq5b@uO2-yrp zdV@!WJSgW$B^AoR07hR0kgratUBp%{%c}G5f6bC_`%?DQZ(VcT%m23Va5f7y#C0y; ze`oz+-~vW6`2xo1VLT&kq9)%uD4(FqL3gZ7NTY3v2~urbNr;A7jS+|$ILuIKcj(uC zX9D$h>E9N|28D4&{e};73 zVx+iHM#FmlBKDDj+ndb@$ye?_D_^O_P)@D&UQ9luuqL+)ynQc_h?puqR+Vz6ro+dQarzPIjWkwl^1#3 ztb5;&3Wq2@MN>@Vu#SEa{y7#&Ac$E$YOS^H#`~q z9;9aTDNfJE6)p&W1@=R8~qOSP%ovJh&x-D_!+Q3%z*|yi;9>1@db+05F+zrDH z3~!i2sD35+MPoUXNRWSY4TZ2B|HkF-=81QaZy{-SRA4FCZuO6Gceq;~N$|$J1FuT% zXD^x}ZJnNX&$5w8-GfXQXy6~yNw_z@CP)Yk_YoI9S*Zz5G{wnH6X^l>J*Or+W&9{5 zTkkowPsyXN=I5ke7m44;8ahD!;gz|%@V(T^{l;tafGaWn)ceif7)wL7FlKohXw$DI z-UY6$#V*!pPgBC~FC;Gw^X+L;E)&N68(-ECS&sV8u?IzdSBh;;deO;>daWW@bWwPe zVe`kx{qg1xkIxbz&drTUr8&cOKQ=6IkTiNs#J%a;%F?19qO@TL=jW4u5`-SjN~y$Z zw{(G(@n1On;W`$3Q`Oj3;59088Ft51!ufB#bwGjqi5G~BoO6-hmyDh@Z1O5fZ=3EV zEq)_sU(ai?i?q`pRnHmh`f|cN1?3f#S6?C!_U5Pe?Ra>h$U_gEA)rL*=H*HWG^bhT z<6$IqlYjKt>s}wjbD!IdrBSOBLL7oi$yX6|@qZEsl4&iN6DZ>uy2^c2r3Z0Xaj*2( z^qby6Ly0#WXGy4hFez(}^^5CjsnpxwSp-A2b%de~Lf#gM$tm62F^KZxPEdeT@^uC) zy!iHTW_sUjR^$+Jo%n5czEF2gcgeQmM;l>dnHPiXugeIR3zv0z2`lkKJLhnkbprdI zhPcIXxwqIgNaN613WDre7U_a522jPE*;}`xl-F5eMz&wS!kEylD%O5o zL({@P7&f4>BYD5$APNa=n}b3E(@xuF5}6sSrH6mb&{47~ABB^K)^Y23*t>bMgOo^) z3`*R8bZDCmTBgJ;L;&$1%Qq(bZoxdfn?M?`r^X6$)vaj|DCHo3H)y7D6-n=;y-{TJ z<5DKkZj&66RQWMrRTnpKGfpbMJwpG_VBMzSnvDCW4TBz!S{kEl>{HcYoTfG{5xc&3o32v{d%AUc~F;6SH2K+)7OeGV~Mj zpB?Y?9HkNUXFwbnDWS0TyRXtjL~B$NxnZG%#y6|#taos0oKMFwBZ!v4GfA2S5+d9B z)qHuQa%fL!Kw-~3HU4kXmxi3O$ z^E_Q#r*sK2b?@QW>hW}*rupolR`~Fb@7##b9xshUG(p4|xE_nMS3}E&* zbCmTO2%C=u>Nub_n^x{Mo)s=BUI_3QO5$2?nmMFRyQ=(nj2f_E;t)B= zzkIKQiJf7!c((N=hzi=f{oT%jkbL)8{KzhB|6_GuTkDvg5% z#Zm#s;DwWJrIVe8&c*A+Uhht6+Cozl$Mt{5BX3Gf7ZPTN9m0saRf-1at{}caSH?RK zbbI21rDfBFYnbWcRxH?SU53mQ#W#sPz#TIJ0E+p%0Q@2%Pkc`VQhwS1!(I;4v;5zT z*MA5c*Z+e<69cG@bugalWd%=YM0f%au@Yc$iNBB)!A~o)v@-V*B+cx;(|c$GGJn`> z^~87t?s(@s`tmIImn&1VzS=IlmQ+IQrGS^sMm3s0zR)=1)4-qN8^CloR={&Hj>Y02 zqC;Ca8)YM;@ho5bu

Ld(pBnbG-G6{~`ZN7Bx>6jd%E2i7L_Rklh&0<+u;fIpJ*E zW-0|4{R^!Oy|N&=mLChsg-s3`sON_hk=2n}r!%9cftA-1{g301+stPKsxQ)M0gYf; zFllCY-UpAILqW>d!?Zz9L_3BgXbB%HP9(LR`hWsRxO?VQJC>j^G3*l#s6h{^k7{j_ z0s`&3d0qu~QIBH(F+p;U2BEJGmQfV!HmVq!S%U`K4vut_?O7~}IA0SOreor1N zSBt664LepzdpFr6=xIIs>As2E)>M3^&z%)3(lUllas5sJp0FzrE4xt#EJx%RM&nJq zrgCVE$++e|@^Pzu(w~qU&AgycQXZ&Spl5*QC#FmWeo2JB(3_ST(755WO2Yc~CEw^3 z2SKgfSN zzY%kx^|Cf*a_8+m%KB)R_+{1lkK}hN6Uqej?JyloCM!BsA~zOx{20n~m{3-NS%k(I zKf$Q$y;Wa97PNF9;+_+IQG11X>0D>iSj$dOY$;jBLk&!G3~{i4A7eWwS1m?*EQT2b z{|=f6%iq}YVzPpkS*59gtdp9MxY;!h8q@lVUK3&H40b*THCr8NZ9G%QguUv=LOq%G z714f3UzIgQ++754^IR`M{vE^EtSb80jvT&+Qo>RF7M!h_D&IUB+saApzUOx%2-WqY zpts<1Gc$M?wNOE&sRnPE@>=PUare0yy5U!PEC0@yCnKPe0T9cinIDq2R6U2;NVVSU zOLtoNfDlXiG}|!)nB%XV=HIf{bkhJYEOO9x!qIMDJuf1HAw-pHre6tM-thlWU=q=o zdSW=>V)`YS#hYZ{MtLt~g9WBHVZsKEfealwcuU^hoE_sN9z~HmB*9sp$=prrhmE5m zr)MrH&&|8LOrFO#{zFj>aG=XrB299#9iLnPUQG%-^7u-<_RQMiLEkI}vzK02n#R{6 z8d(JG0ya@j#H}XmIvF2Cd`FpY8(DFSI-maAAhlb#V4#jiAeH-G+`>Fko?RJC6Q$6z zAO0|#{POAP)4^PM4)M=9sC?$=rq3_JjMz(B`TQOSrJ8Hf7<_(_TvtB(>?-(AY%~1F zcz#x#QBM;E?F97XYKA~Pg71)3N;`Q>YG&!*YrBcUQK7L z_P;$V$)`MsC4-9M`zQsq%5B6~$bCj#n;fYI__-WEmvzKXaO=8QVGjdR`3ru$4-11V z?B1!+O}X~G5U8vubL%Y9>4BBqJ7BRu6aly7-rk))m4tg~tR$)ifn|Q3OxnNv-IC+p z4DMi{6QRE1gS-Lom(=XzLkY{5mY>HjI+HMQ1wItx6#7ycY??b+Q@A6J2U9^RZEf5e z7saJ_dtwz-Vp%C+66A^nODKgiLKba47p|24SXU!)ymdlTl1E36C)p`;$)#Kl-rkl2 zsrXTr8rfbvGP?6Z1^QX$5&vonuivopJeNyDKM8)OLC4#e_`LDtP7y;MkX%Ro`Z52O zug>!K^|L$;rw9-}1HDE0Sl;`fCx54S21ib04jLQ{KYg)+=l#`*^gG*yO`Uj)%P9v{JZpa7)L0xjp)GM>OXN&0rIG*pkR`Z8v5*%}2s zF|k0mVWNW)bzJMUFmzxum5o&#O37jaBMWEk>9xjD)r}Ua49>)3ZRHf;}<}JZ5U5)GSX8^b+0r_(aZ;_?#V)q7Nlj2ef^ciV+8wa2p^7 z0-P8Jel?~*Wh!&auZ|5!tgbPlY^eV}Qg+8VSjTR39Le$-k7^)JhuS3GTl$8j$!5KJ zFWf*FP7-?X&6k73A$bqWmh8n(qS@F;e8OU0Xtf|ZPCONKHTfQJ{*WE*=2Qan%H6^K z5RN)GIO;Fs`XE>dhfXBcSK;g*ME-lH1T^1O)lG4@YkzXwDjWFhPKYhsA{|HCGhH2e z0Tf-=6?h?JqWn^{;fCB)=X!LJfx-xyt9L#PI>&kdlyO=zl>Y{QI+?y7XQIk|a{g)$ zh$C*y#NG^rYzM5h?<=02bG=$AIe+U(z2x*2Oxzj*hDoLHZ`MUk^0o1$DV%r)(K<#u zWpUA7E2arxc=&3N&Ks?2;x58_FW0)!AQVUxJL%v((L4^q{fJ$i=HFUFC`E=t>+fk$ zJ?7BJZpSV73SNlPDf%sb264f77yic3+1D<|_ro9Tb0R8s9#RFJDW@mXF;@U=94dWZ z!7i^sbvh@R{FpHO;(XR8y04dB)8uTTcgD zrN{l!AG_Ekl^YP5a`C-QzQ70$TyN1&ti-A}?3&$d!gu~g2LcSNyyGaL-dC700+yI2 zQo*NU{M$G~f1zvOwyF=NkZ5ww&s4PKUyt*ZzuV0hxZz{coK8Oa^U{gJ)Mpy$<<{|7 z@_00wc1yM3cr43hIiIDfe_N+NowKelg1;tXy^9^o7NL9?4{zX|w_e;ED-N6tpRX4W zPUrW((m44%1`Gw2^Kaj_=iNVL-}d-0D#@MQJ4LNUEweAMST{ST(7=ED@>R$n&ttJ5 z-Jc5zv}IC-In!T~+)CMXMb5f>rMrDwH^H?y|01pw9qkbe3XD|w8{0kL##`@rfR67g zuwNkDel?QJ(-$H25#&73f30|)b&OTWz_gKJkQ0#mzc+dq)3JV1?BE$TY_b7>Rwb&X zn*GDW=+GCL-U0Bl<`XQzX6md5a*UE%1D3(*XAm7;%njlKU9;o0g*7Mncf-L8h{J01 z|L1M~7bLHOIwu08HFZBPkB0{e77%p-FE2t3K^6p3L#5j8l)|IWCgq_OMEjymjnaxu z1bmqKuD;Nm@!u-0HPD7MuZ<`|=8az!GM0}KGqiRoK`+6XEu8v#?!5=e76ds~z&E{b zS~Y*CmHt`taSmY~^AAzuYS4IA&qk#?$a}f=G}3rZL;;Z{X)(N^zCG(=b7OnGZD6m=J>?^R+C~;q zL-Wba!9rt*v?GvFXvd(YAVPb~NPXKa?g4Z}=GcB-Drifb3&q(kX0Q6PRtyySPKN^W z^Cujy)#qQIiE0K9tKnl_Il*S$6ApQ-lYHI@S)AK*HmZl`3OQE+V!JO9iCH z*s<~-la?GiIiuW$9vMoc^05x<$inp_SeoY`J3TXDuAEHX*#@Bl$P?qq3_c|!W$j|VVD=#)CTw4mR4T})b{Vv_m*v$l4VvFQys>F zIubFH3BpY|ils!qCiQe_wI{SC3r64nZKjwn3~GYOIpaJly zQY^R%p8-(0dh9d}3moi-8q-ym;V_@>9*PXywEnv)r8Y?G%oK0g8`J}~A=W2mghAxU zf^K4eX|cm&?E^2pyRI#0UG;kHoUMZ13Ypr&C7C=6Juyjgom4A)>@L%?wd-wWxTW4Q zC#{QpNA^k?ZDm5s4-Ah=N}Ll8z?0Esf*c8+tQEJ##YlarTZU1lhF`ZM<&?m4=fQ{R zJ|@Y92xbc}Y{zns47jFDk{@*XlKW99FZG{y z?m+APP;8F|rF1lp&$$`5@ddHOmht9CtUR_ZGZiXa<1%;ap?_^D&E(gXKS^h(fx@0S9Kjj#K)SKK|ED zZ}T-s?&T%&$`wErkGE0Y9#8wjADW2IeNAV|uNvT686(~N(rgzhKRg8Zd#b`Q~7=wIvc-rNAhJVm`< z{AH{dD0?)`A2{Jl1Sacqe*N;Qjo z@*tdY@y{Q_F{*1&ES>hOz2O--S{m*cPXwDH<*+||ImG(sW66{5meJ@r(nj?njsk-s zWRqYR-xlvIo>%fs{@-ZFe*wzc6oW)d9nh=nPRH8Esgcv~$Bw3?Hrc=QSQHVq^%vOE zAO$PP>>R?seTr(GlGf_YQww+l(Pj}%Q2H7WL{SK&xh>8P_;w1l_r_X#ay5h2;Rq*f^P$0k*3z#vEa+M0VvhnSH+yP`05&}dJWX^Tlx;&d$@`#c&@S*< zvF542uWb1w9pV!X7m1w-Zv5tKBI(dJ2m%7)z}$^*Uqyp4atL`a`;CENIp}fzEx``jsyr-K{J z$OiG+6e8j-kG7WjtA}zuxPZ=i6abb2VYYwX%o&^g#M?HVMQ|rc$S@P;O;$MQVbuQU zC{m3rr%XM|09?GUhFu~ylDK43xMjGOgAFDiMut`u&rT?P{ydP$d{)$`E~+mq{<26+ z=+)V_V*?R7VZHgi!#da%B_X07we(|Z_h$F^XK*aRb%C$6kK!Nv4-Z;E4AJpB<0=?v zwu|RAkO8g&#zo2C*z(&r{FTbH981$^+b=(N0rjy6z|d5~y%( zrA=Ag+3z$A!0wMI;JdpPhC1+@!iEwuDDB#s7x3I2M1;@Il$zVvpO?%$exBYIbU*oP zs_)xtYxKBml7iozRPpx=P8b1*MW}oOGLmG$3!xQma{3evXmWh5&&@W2z8m05j<_z` zjfdvpm?KU=u6BKfg2}%sBN5h4+Sk}n)`j7=cp6*v6E$XfR!rt_T)E5_6Lmb>md~ea z+gu#iXlJj&{6=i_S+(d~&hqNj%&+7hIc0d7@(ok|e?}VG_Ee-a@Wq~KWTgT7efI|B zuDNy*C0~NGn??jYutOsEPLJLi^=Y!bOv0`cx-@*xbJi3y(|ccG2^V61k0D0G(arw| zlT3HPuAzVSdgUik(P01-NL`PX=b87KRMlnLzveiX2dn)*Pms;x8t4UU-Vj6q_B{tz zfY=EzTfl5BL-jM{wg3MW?ywPaCL~yvWHa!@f#?Y$+1|Pnwu!WPxP*;=sXz$<(If1A zO%mN$gj!3%uANz$N(BO0e3dux7c)vO{L)ZkIabe8GO&irlq3A}EP z%DqC0z#`Wn1hS+g-1*W;%6K|4#mD4H_Ykx?r1rp*>pDm6S}wASRC1T{Po!3Srh|lS+)oXWc1<^EM>4paETZ z<&l`5Q_`?GQ&p^nd2AdA>S)LP3;|ScgO{{ZA6RSHftq^b&rb|K4#6gKN6FBwd(`D z_Oq=+cKl9g?#K5S61My05!O3Ku+nmO!fWnnd}M_1;f;`49Sj)Eh$7-XU=W#g!~&7o zK;bQZ4tK~$h_yT1UT}8x!h`Rsnbn?RQN8VO*c&(I+vNP?O9BKKOAKa$c)q-(U$L0{ z3@5hclJi?d)R~z!Z@Bx*y#szgE;uS|8~P%^6r#Bdt%wuJLidm4z_%YJn~;N)u(M|C zR~LBtp1DfK+)59gvJw2Ic+<_#Hf_~V6R!7xZO-jGd34xxjw?%=Po$LmG3b3g{&jco zCp1J(mdg9a>FcAiH*Xx0a@xn1CMmZ%cXz~~=}n6O<+b(xKLr?=zPjn?w9~_+_)GuW zJK3G*^UsrJ(aZJ!gqa|d^gfjyKVEZ3b2!~H_&cYPn_{TsH;3JXRgk}2jW zFMkVN&kM{S{xb)>A!z^-oh>Z6lPx$S`mLE5E%Vg(fk(oWK!-jN+nM}dhtH-TKEk^$ zKo6bK9fEwj@1E%WVV&@NDbCJ(PcNL{IdF?>&PsqkY;yGQ)^-uRv~oo`92xxhgI@a? zdx&RW*P~B0)mR~#$`jPnu2egB6~p>9XHbF4^C_`a3jME-jKXZsp#`WlOU;+Y3%0eD zmBP+u*9yfV&h5wYtYYgT+LTpo2|dlVw>0*gaMh=J)iVBR_kG!7v}LC!eWsz<2UhBO zRH8cpf%}38v(fhnnGT0aLKBgAA#cR(4h5~`+`e{gm}@Po(_~44h>8njrunI=@HBL5 zht;-@=JK2Hq{qq227JB$vNpg{4ZhVwUC_wllpY_?mstMB+0|{!Ep0L!wa+#*+IMjU zFxuX+4 zWiMh=zUB9p_sk}Nx6`jITPhu^GYM1wULPR~|FuGi{7+-@Ii8?VYe^F2jZcp+$BfA_ zUbui;-k<6F#!d)aqsfTBy%}EGbeNgB3_$JYHrY8kS-R72z#4H<|9HGHa_}SLj#r{H)&hZt`!$Cg3=@#+`(XOYZwxV`@lZg~ZQ9|cvs005F!!1_%gtv{h@yIuo zBHCc8>CuyhW(5~$$fchkz)4dYJ?U~6qb}%f%A>yUIR1v2qSVxGpW^T7wM0<`+GbmMIREw>;^tK_l2?e!p59OSNeBTA&+-?TWeNw8f-UKhL$=SN!Rph7Cl zEt*N|_5*^jh`_!9K%)De6qT&X@GDrd1RR5ahyC|4$9~tZ!7P*5M!oF@zyo;`bQZ6P zyK~tG!CedV%s0Yj!8d>?S?qrN(grZOrhj)(_ifp|vRoH6N{qJ_OnswR_rKE%GaGhd zUJ3x89{sOH)`kE$qXBP@GPCEB0$EeUL9L5AWQo>2Om3gj)wad1_;z`ra1^SeDBi)G zk+~z;x30*_McZrD zy?!M&qg0wayBBibnlsnUTPzckg`5}Wze=QeVJ3xn;Z?F@;QXUl ziFi-NklewIoE$qM|Cwl$0-Xj5d6SQUcQ%HOUC%FHo#N6$!4y%&0vy3w0C%rbZc=yZa*uTa>gLAMN~oK~0}}=66n+Axny(s@w|QQOmDOT9XIG zT%GTs91Hjk_^3Z`3cQQR3TEo9%vZrZOa7gbCdvFU8>QArIr@dtIsJGzezkS+;}9HV z#AGvJShH1BPc0ERl{3)d&a03Z%b}*9@S_j;%RO>%cex^Nq>iet$H$Ri5IkG=P$@)d z`15ME0}}IU3)?FPPY~4qLWWEd2z=m|o3x$vsL}=FKEb|CT%D|F z+m~@VXcf*gaOwCUYCb^ZzPWQRl=Yw9+8he*_u-L$_xrw__+oLd2$=qu5{(X0(~To( z5a*a)RYI0~Ywf}8F8l}1q$hc$*b581v;m)z>yeNVDcV`wnAlF=<7U+Nywfrra$uO7 z4pRX0zU3b9x^zjQPe10fqMv&e^b19N`nA3b;6uaOdOTxZXt;=e-RfBi`F`QqFSP^a zRN1BSDzf2UxMH1Yad#N26c<4g2kQ{e(vfdh|F*)bMoZl+F0DSg)kf9tR_$q0wxtL- zA2#xl5ateK$hp_&YWJ(aEqW<=y{eZ;wnsw)HeZ=flWMHoSyZ4>UG1xgf7UI{I0*Pe z{aH4d;EVWvB8Ma}?AS{amw~QYKM1_#M*MAkzkC}6y?KbbCZPC4Y9E*NuJ3sILscaM zx834QkhhuyGeMRq=c&@h>LFGK_Dmr^aY_XdaT3!jaTj$?&In2}BgjC~9KJ33lwbZF zOmIGqiyvWRDR9K_dOPpL?I~U}J3_z1{%ke;Fj(CqCUz^OAI-Rqa#O#Nk4inWtE{$B zCROF`rXvk>J1;lnQ;_}AJISq>(=_@UZDc7t;1bJjt>+j@7w%TXj^~CWR7j!D&w_>x zIL-cjVx#1*ly8_GQ@AvU@0r?<{-LY4IILohZhMBeUs7Gj5PfkMt|y%iVu0o`)xM7yAOc=T#W2wMpF!$SY z+_)$g)2hU8_5fvd!^fu}jFY{TT527tWNoQXxo1y&D0RcAb|B1=pp`JgSySzzSU=2# zCKo0Dee2l=487FL_Q&hU%bC~LY35%1hG%kIRs?kcFJC!)2P50EWv@lheIWfW%xox$ zzbQs9HZ*jSP1hBcsW{@OHrLpd$(djM4f*^zfnupYxLNIKf~ptaeFZM@Dmn~Iu=7}f zWAI&v{${bLxWPBcj9*Pc87(Ah!jDvj5)aUu{1K`3ZNW3l*ZBpY^=Abi?^_dmDhNJG z6d1AodF_w^@+0h~zSTmv5_d;KWN#w_#DD+M=|we=VxnbO-JOj|Iom*Ghm{8H_4VVeuO%jYBdomx%$@ z92lPWlXtklYe7X{P!p~A*oRb2Umf_W=j12s`d0n=U&0I!7ko$nlgs3(7@a*CYV;pH zIX!^LvFxjU=FFWbp$%LRJHk+KCbO~B=vB50=J;8<-?H-vcT2u^KCv>lb_3VNihwr5 z;{gY$iiX6vG#AF~B~7=E@0j$H2ynV6g18Tybq^Ov-8K3t=arN1se0W^i+NeVTfi;n z2apU6W*W5O52yqQVFo}QrniVC)eyCEgLi!CC?|&1l^t?iVnL^0P8ed4p)e>Pt3a8I zoDx2RFTCD4y%)U-%)3A{r@Jin9K^jmg_7Rub<_vK--VJ1XkV|{(hU#gPEHs`DAWGq zz-Y*NtrBv55EjY%l>xNgdsUEE6~Ai}izQHhtIdbgxfeYJ$85ciK-XSV-K3gb#t3k7 zfPKT361)Tl^bNzp0zsb)9kKFg~14_mi-hKD1Fb@m)0dh6A z<}U$(vlT?d1Rt?aj*$tbgp=*OE%<@laS7Sm~J=jE{F@&3VR!Z$~{wCr&T$~}6) zzD$c{3!;~Va5IROCR)!OzlA%K#;bstcLQnkV%`I9hApm8m9ZCSWH|atv{X+mG**Kt z%osL_ZlQ@Z_H-neh}{a@bGWsv%~89Tqyqf=$dcABde!V_ykPM?3#OWMV$Ks$DnE1? zRr}-pLK)%vD^qA)2yFU4a9RvHpJ~cP4AC z*NbzMMGK|S{24H>`vob##ZNu&zn?^KUV=kk!>4wd5RQ{mGAUf35y?6y^3>anS(jeUprzpb1S8i1 z4~X2E5{pU}NUk?CCo#s|@tjaY5oo$)=Io5OIoOuFtRXK9b@4q{FP;X}j^AC}slbUL z2cojdF%spb25Z>5NVO`qR$j9O9bB0}sU^Cq_sJ)gI{b@9oD^iiHiITl?LGq$VECA* zQKHoHAUIwi_z7C+1*UpMF(SykL_BvzPv3r#CM{%B&ZM6oZbG^%jX%%fimv{vZg0gx z;tZ1?o>wXYRi?PL-^IKjvQy8!;PB1Y=0o(tB@ z=DX~hVY=K^Yw~c-{@(h7&lEm%*VaSwa;+%@!g8bmPWro-)n1(4dzSBOMy{blhL6hn zFCu`H*v$UxdtnLCbFIDYt(ySZ;VorpQdmjjl1aRifpMyxL`rw5>!lZ31aSV)Wkl4B z)TKq+;{0nF$D@^1XbAo{e#=a?W|P}!B}oMVPWuup?`J-#+*{{uhBhZt>$?s-ATMQR zrugc+%F<&hC2~QY928rh4rJ~p6&j`CE#c)666?3A#h)daw)kS0k@t?7pNtW|daNS; z5Nu$*y%w|o!==dlYe)t$I`rLnfX+^=K5MZ)4r3C{(J?fMGxoiMbM5+}Bc{|%*L#T1JlPL1EAH|P? z@VUtwcKSv053)Z$B?&E@9M^SQ0+sNgbv89Z=Zt0N&5F4lB$Ig3T!wbyS9R1y68#YU z^o8WWGxeKio7%4yira%ZxpHRb_tpDz8hTz^JpKFSfp^~noyvVxF*kOcw^X^1%%J?s zh9XDK9+O-sfm1c{5pwGmcK?>>MXPR#`)^tkCL{&f1T)&H=N(~jAEo^(4H7I7pfk;> zm*`>UGj;hS3(^6tp>hxW#^l=vI^0h*`QMh~Jn(fF)bMLdmhGMyn8?l>@K~3xwQZmH z(d5OS#kkZS^j_ZU{%Gd2?~=G02&Tu{GexyuVp9BB|MY56fg`D2<`vvm9y(GV2&?Bc4m*;CQ$kH3L0GQ~l^Q}@e~s~Y2L9Cy$a-}CML`r5@u%#3I! z3H9}F2I8s$ZPx6Ow|e0*ZD)uqRJNcrVq5~a4@RC7rdooi)^p`xz}W#1X)Ol^%Mxu% zzSHF&T9)rPBF9`7OW{b zHTnJ1#+T5NDBJdJwr}#oc)JY?0ft&V5r*iaprr{^k_Y__$JRF*uJaMdl z_@eyWJ^sxko2nbohx&x8G03H1gk-jn789g)_0GNT0_&F-F-tHhlJ)VWpN#oIr^Z{7 zdpdbsHxBd#+LLzNj@>fyC9CXNj}FNHBc)(Xb~b!FimX!(lVoXfz$B;rDtr0aCmHC% zz=d{McDPq?woCNf=ohj?V>qVo2V_l%SSMlQ()-8y6FX)HhJH6JQBt@MOt*Rp!`j-} z(XQt~gVT~Yp*tf(b+N$b%)Y3i^!tExl0HqQvSP7#JF7D9_sTEp9fReSczK@5^P;oE zOZDHDF^kvGW*;Tt7OCJ{Mex_iWk-U1jv~HSBiwMX8SL18S28d2yQ*kA&L)mvDj*h~ zO!a=0>e~7U`6vo#e7kDcEp=P6s)Sv1{`$|BIn?ZNgl9*RPK53 zC5Pn{@VI8C3%_-cNW|_kW)Ja6dq?L9Fnq-33Yg&?M4!R`#VPba z%Qwu45)tw5FIO7ZtP8@cGTZt<=GFE`)_v zOWFbvsms%ScER|``+s?DfDr`-*!I?f!JV*DQ*HKw+d2AQpSnx@wuG=PyZ<*aZ+!Rv z%M#6_vIXSt-ad3g@TBj*KuEh$-+Em9Y}Pr-=PjRYZxqyHFh2nY<9t|s);&Ofu)C$8 znMWvhgN|E@Ne~wg$^PUpuiH^`Sp0jtdUZ94dz1Qbeu+peeD&SSRd+2LhtB!j8EWM0 zbtr)!iQJlK@^#Z8b@{_*L+VIPTIM-_51A<4!iuf!(rMRy2`MJK@8({pl;Fw9{O}KqGsSItTND#x(&HxIy_+IEY&z@a!rfc8XX_{*$GV=g?A9m&4Y`Z6@rdn0Bt2$#S@n&YHXU%srw} z)`k4}k`I^+q#c6rGRP8|bX{M=NEuvI6g@m%j>>9Ek{9^2Zan#!x-)Cpc=Ou^c^amyMsEOI`Hyd7bU1np1rSlD_t#P33XD!>?6CIgSWf5m5K6%aiAe$=>xH5P1-26 z*hVR;8LEvJO`kt*GuRxDiDvVQku*3QSee8RaguvxfxlYxS^g9 z(F~gRdx0*GAa2$YT-^MHfOHRrof(w>&fgV)y>ZPeIu~R_kYFr{AG}R;P2#b&6k4Kg zO9VFiSk>7|e#zV65E==e>@7y!ffg$8c+A{N$E0GF$K}p0?}+1)XI_V_`dVz=4n)Th z7ky?FjaqG%4LZtLqyD+|`K;OSVOqOLXv(2fhtF4#%x{$DlmTMRZ6lK4hin$SK|L%? z`woswgy91GzAS0KB^FiY&jZ`v8n(q;sO(8ASJ#uKQ7;><@IAfLaWzb!x-$u>oX2`h zB%dyK?T?i??@iEAENu~xF!J~v-mf0=%g-h4&G~ALqM~mk$+K*yq%!cHl0|uI%un6Y zkxu!mSSzl|_7hrUskVuy>yp|<9dq!2&zRX0%g6lr! zM2p7)Hq)jzZA!`vTe()hT?5O`!G142*S(%Z3kXH3`jzxZ!}DM9XHrdjb_odF8{}@1 zaqk~_Di7WKeY|i2UxTIO3z%6?k?!w?cu}?bB@MWIH)=A5s2;g*$+fa*J}7#?@zA@c zLNoqVms%qJ*X?(p7wuf)&1)t7n?K+{iR)tYl@q2_vQ31jzwQN@uvAMb5`>W&(6lT~ z6y$PQGkL>RnH~{W(nzw^yPJig&rz%%P6(PPEMViz&pKi9yqtrJ`i~u*wGnOMB-Bd^ z|Lk#RM({jlG}WF}H}~8QPXj1(xR>Y(K{5cDs~c55Q-#oN0g!3LV*49WC-sUlpouGX z^wDC_;|jFsy3oc((&^=_%VrY|=sASob#T~&&ki^#Vt)@Gj^GIHiDBk5Cp!zoAlyMI zi)(M}eixOhj{*g{`kJ#gj8%;(EidX95X5-aD?G7dKUJ9q=?yL(`F;(86(pfII(LAc z+#$59U19w}{BGV^C6Qn&C$Z|xFXPSWYn{p#FSL9IfPk!GI959X!+R*ngVCq7-M2kg zh$#$_m4xz2>`I@KOWr@@2!C84gO;4*`CiT3-{xJw5qGVxYmxzWOpQC|VjgfaoeNkW z+so#iQ9yAM*@yPN3wiR-wL)To&P)(N;EwN0cc|OaTN}v`&ybK~8G(04pZrd;!oQ&Oql(S{*#T%^&3VCcDZs2h5#9->L0p)Gak9@G59F1e`;G{vT0-o)nzNl`!PPb z+aQ_!5=!nb`EAkICB}?x1uSW$cy}a#>nS_;kRps-E`URFH4C%3qfg*r02*TriNXml zr@kRVvt{iVV4`XZLv9H3N~eOpxV=_MfYRO!NQp;z~9 zyq{G}_XiJxZ1)g0qg_C_F8iUB(MrZHFC6$2ag)t(G!-1QK#z%((b@&e>HfG!F=|<< zWwugJ3ool6)wu(mS{6Fbn%!(Ulw&gUT5cTA{~pkmV}%}xsSXDy$KmXMTcdg;4-79V(b_ev9%T#^*ZyRL+@ydiXK7? z=Mwmfj*r*M4^PI@G6MJv!TFHi7G8vGwq;@}JSb~dzt&Wz{vYUL!Hi!jAj45^(s{9B z?@C@vZXc82oc&`aM9 za3a8YHGdDdJoq&OGi#Ds3_5p%frGD}GQR{?HX!c*msHj{CIrCS*Vw}<=!;vAH=K! z-7|EUn3Pieuxgj$cJ{-{E!j97^iTE+_&l~95z2R;L#!72Z!#rNzBWld5TC$v{npoN$!180_M|-7!!{ZwYyV|I2T@fp@Tld4 z9Af-~K}`Yq!kst%Ov*QgIHjJr1y^qq%Y>wwbDucWwXeKo_c`nTw`TZY_tmIS1dhgp z&f#mJF@{KWB75GGZ0WckjILcm*=-cIq7I(x@GS?5;)=J2CT;;lNK01`qsp+XQ+Hxy85l=WL8YWn5Otf5DjJeKI#2FZ=5Pd zl_B1LJ8TPLa}x?|Ivy-b4+r>QEw8&?7!l(SzSQQ!7|j&*F;Ucw!QLtTxlhk<#-iK9 znLN`rk?6$($UOLsI1o=w_?Y}=H}Fb~>$SI?f_w$So?NY^YjC>l=;_+p3J?r`{Udfs zv_d8z1Yv*-l33%vsH)!!2)#)8p1X-JpL51SVdR>@{Uu&crcS4+pKV%g%Jdf}ccyvu zM5NPU;5cmL+^Xd+=+h{-eb;kEcu6~Qn+mYS% z!JQw*ka7N2GarZTrLuWl?FUsBI50E6#nADzfI|4U1%zy70LccHq{JXGO#gUSctV6h z!VQ1@0mdg1eEb5gV-E@8_4|{=d~~uAYrSl(9U?@fPI=q^^dtIYt9$Y1hNWxYHezg` zN4Ja)RxpacAv7kxYt0fAur#EXcQ!@A&+5=ndeYJleT{OGZ&}QdB4!kM0w6D&7_yD| z3giD6QKQt>t;cKJ=XTU;ykg2Pgo~v;z%=iPB=m~~^1fJM-#$93*)jPJI&YT4w3PoK zBzWo`vQhD&ZK-A*O8SZ>9T9e3{Yc~TRprjIfIc_l<A!t>ZW!ZAg zlG>WTf*{4c@Mn*x-00pQvCyX6FM~dIKL>@5Uer&DpP%%+RK7>b^A>k7fA-18?X0P_ z)u2JYe7ER4tqd~rShi=I=B!{pA{+=<4KcShm3IJa87%06Yf$S_j>3l0CnAxsUb9U+ zlkaA{&Y{fxy6-#{HWq%}VBiyNlmX}566EUD-aQc*crr>@oE z`@pBOj9?P)Q?HLAXf29+JwA~Q7ECbcPR}zTm^3UF)Eg72GYvIBcwUl^0E#JI>c77# zjpvAhT!dQKJq+ctUv_d-jI1tmgsU0t&HpKlpUS^$iogIOY z{(?Sflp)uf^Qg`%0Amp}p`7}aXTzEiFhkafVDL9~rMEcJEH0<1>P?inX+4#Es3 zZWutN_hR$!%MvrhPl_oT&;nL=?7zPe6)(K%fvR<$aM-%#kct%5uoj6LJYZ#3kxCcZ z@}*(BD5BcGmFRw9Ht%`p`j^s|y?OWNTv3VE{~e}P`aRcYRJEyIs1?Oz3CG zq>Rpv;@P(9R6pb_uyTAd7$Yhg&UMZ2T{_Gp{cK;jjps07nfiVHa|VK*&XAutLapAf zjZdE~6$$mYix{)sA1f#=A=uHzmwK^dS!n$WPJjG+y6D|zw4>k)G^@=-*We61s~^)e^GsCyq6Boa9-??hK`&&n{i^ZNmdY33_&ly3)Ao|5 zG&|tFARW2wK)wqw<3TULjNKSRsUxhDCA{RWoHZG{PiY6%(2*mhd}{ysT970xa`F_M zJ1>u&CS3!5ZU9@iYX!jZ?H7VIYRIw#*c&jvsHeFcE+xbg|9a(HI}piOmeP~tD<7H# zbIIDZ z^R~Jbv!!KYz>J-d&I}!|rdpR8$Lbd(5{DCpw^n{6UIp(2tsaYQ;r3SsAHGP}J{t%@ zn$*=_uG74Ovf`e~t;Xo*l5bFS7K?|O41JZ@426BLlyzJnaJ3HTPXEf!pZ1_6J;grl zk&J}>wJNWUTyg3T1n1Hy**Xewc{pl z(jOr|JwFgt8}giPw&)SJ>xQ^hSk{`BoBAI34S97dXvSUVM89CFVz>j1J;~^9{b)K& z{Fp75j%^d(2KiT`26q>5gbJai{_WhsiLHn<9^YvUxQsZE&3uG)^R2d2M>4m!5#9xp z9f5|&0&A?5D{En=Etvuz8@SKT+(X87sJ)ltE<9jqRb?vEingR4T^PV9^uXhVC0KhLwSDzomJ zo6ZBN)}ja3YM;U;p}}4I6B(@4Sg^z9S$3x`(I06BgjVDjsQN7Ly;d3Vr?eT~rV08F z1S;}F3^3$)!YrJZq3zTw=d(9nh6u}HSkOi0->7zDzBvQxG@P8XbrRZJEjjtuOBHS% zyG)Mv6uJw$&+*G$8EBJ7q*=f7?R%IavhzTTDxqhrl^+LN?}l1&zF4KvxbMYQrM{d! zUZkERAFSgy49`9Bl35I^AHMwd@$HtOhAIz@s$WttD{ZE9GA!yf^Rv^{cOvt~L%X)j zTo59VItL%_xnSrB`H1&lNd1RjQKW(Kj)gKij`*}&JM1qz1E~_?QID;@`7tFk3*=OZ zQeS*qlI#u87P)ys<(vB@nHzSe{xG<45{+ku(zGs2arOsq&bOaOR+neLvAz%Yh1uF8V#*hlfF)58SSHmn|or z{ce&pHNcbb{^t0n?QVqLRH>;D?OH%_nY-vGml5qShK_3V`LPgYw+7lvzqDn*EQJX9MPGU4#lY6F7mZ<3D+x_yM;1LNMT z1OwTh;Mduk1HZO?nGbFjRzopC>~E3nRf)2@;u>f|&VChh!c9`wCV2~oWqP5v*fA9% z(@$~FEAPo19$v3KHNFp`e(hB!Of=rq{Pn=V?Ir}r8bkDA&aKPo z$^#Y6?CFOQj$rUqX}Mo`+ol_AlPvXHK9K(~DZsB695?T<$p#)>A^fzF8g7IH@KJbCE&37=D6-}lqz8l&V=@#fkZ)%(@mAX_9y0Y7e^ z;x!2uyp8LDx{T3r%=PAUT-EE#xL`3){kydrzx=LO40AhZU9m@Pf6C8Rkb@r8Kw;LO znHsx6sLO=?Gj0k)jIKEyQZ?ugIyuN>A{U?qY6SMF(N?G62Y>xBlPHOWelHN>jv@)L z0s{LI2qp_>#0#4OFlz;{`0$sU%5f5mE0M6oguzLLQV(m}q=rkQbW+3kEa77N3o-F8 zdyP&tZz5d$#2l~aMtrg-j$+)B2ML8*l?CTRzVd-y3wV>D4=(dj6(RP zKluqjC1iHzr2xZ>W<|!2tj}!4MH#mh7k;BA$6~`HuT4-no4wT&Z5TDL`!CWDDENSU zer!xRIvF?{Z?kTc*ix-dh0CK%5G%~be#^0iF<9HDG2;OGUM8k1q%EesX)T$1FCT#N%7)}2Z7#G5&)msu!)QMFWgqxv=E?j)&aJz7^) zzXPEd&n*Zg>^n%iKcN`E@v5yb8_{v;6DqN`GT~phT0oS0Xx+)|WuwbAT0@?ZoEh7f zHxBcDox9Ct7_*!)pIisezaxRdE@_N<0ajIOr$D~IW~N^ZS}VjpfcsxRU|O7sdM2!q z&hrg%dOh-Qtb(Y_(wcd_>}cI*|5b)Hk8ne#%{{5CP-EMUo9uSSn*4)Q#b#T=))x&A zGC9(}Oqkua-8s_ES^P*i*)4rjkU`U?Z`|1Jmc1@})UDCCy!o_61{ApKV1_oD#o5Y+ z>-tx_*t<0`*cDQy55KVTNWg6gN!B8>k;`hiH{6|c%@BSSDd3W@H4gV&{e0-Ix!*SX zFPu8=<+*DJAv(}HLn;oEU%;(4IMFZAE6YyKsdCH#scof$xI)T)N|w8J_Nyk~8}I}r zP4mO^z0!nn3OTFl<{BcR%-~YgXi^M0r#lmOR=uoeTGU-@m_|!5yo;uSZ?M)^y)ZE0 za>06EkYey1bi0a#ZHaU}zDy;GD&E$Ug6ZcQpe}gGOK&M!dc{}t1bH|7Qf@7YKv~i$ z`DiQq*X<;EDSzMxqx90f0Xo8bmk-=d51zTpY(O%qufu#SP-ZZ~{07WqaYrKfULx~r zsU3hGT_^5Y6)YFm;{c(=1U~&oel80}-F+W#iNU#yzSV6#*0Uj z&-3DWzhf_U?KpnF>-#-F=SSUu$`txgPKXmm$6Tki=nTGbz4Gg#U9ttD;)us+PBzuU zOsdysD8D;RC*-3Z57MT?2CSS%BjvJAa95+S>K{0}+UTZPGv_ksCG26Q_3j%$nL-0? zEHoR6@~<p3j=ZOFlwLj;WpneN{Zyx#S;BKv3SNULD;rUIHIL(h{&f_R{f@Ib z_naIsiP{ic1@EBRmb`T<*~HApqj1>;Qy>27@y1|3R?T5NVd~kav9bqBhaGEdtBmV? z6#}@^TFW%P!?NSVVOQE2eSBnvY$vW+X!LZ0` zX4>#+p*L`WcQaqLcm1z{J32v=I{eXCtn~q*P2{)D0>6Gey_}`*0*E2Y0K~7S;_o|x zpLo6Fuwtu}MiAkVpE8cT*|vZ9b)zcMF#G$iQ5oVx-UlwnG0+jhCNT~EqTxodo`;U>T5IZr?CW3X4pw!%deY~K% z8o|BnLihNIkQ@xkX=kNslQZC)Xx^NvO7ur2>DC7bJZBc3|Hgn| zeNvYpPCOnt_On_+%+g{aLNsTl8s3hP#4wd3qDlpku5`c9n_v${%+(<7i~Kl05@406 znD+u-*ZjFN)7`GR>kuSxTi87^PLRG9vx-A^L>Wz*voa zagr(Cl9C|coTTqu{AifI0=KW3z-{4&cXE_!SZMuge*&O&3;VMY5Lk_!`Q=cA(ZaI* zOl89q26`W@er0n2J;Ig4@%7{N1(0-Cq+rb7_^aRx3IQ=~Y$WcF2RXC+*4xJSpoAZ=H#$hztXfhe^VvQcYMLf> z6kM+dDK!WOZJ9)Mn51O6Dn381&3=|%nG@{gN4OUm^nsTRjkNI~!P^4V?{up&!y%GE9dy*)S z|5UN_ml=`xUq7b#+M4UrzL|A+nI&6Q|my8d0~oF(BquV&L+?pox24oqpfB zM~pV73V)IC>svE2nCxY^s*@$2TEDQ?k*|ruzU7{(fD88lman#MBUnB=9NJ!HxmrMq9tRofQVDeiz1oF-tun7UeNsTa#ba+Wmt@k!q)=YeuUEZzNTgPmaUKV}t&i0`Y zmU8m3K~wa|Ew5)|$Fi+A_y@VCIu>RL1=4t7o51c@IxkTWe@hHxd;hkXuHAJ!mk2X_ zO>U+QD0Xx%TW)?sXFz%bc%sj^A1o*%hV*#L<1=Zsdb5~$L?@ff0mO=mXQ6V%f z2L^Kj7+by!+!WJlKb-}4@SrBg)8H~@*D$aD31a=H9u!8e9QgeA-TzwdG!c+}>=viX ztepB}(Y&C~(7HW{L>YMm=O0()hcu_nkwJDWOhEAO64#~j$G9Q4m#9usst(DL?@)yg=Nn$t2KBI5&k{E3-y;vN`;oL2`i z$M!Ein3M4e`taGW?euRF-T)h5o3SmeGnT?v^6~cU%t?~b_9QXg^0r1pM|9lXdeFLs z1%^=YdkQcN<*eutAAK|#X{wD3*Y_YuC$kv9IGAR5j5zrS-oB3pO~v0d$6hx}R8W-a zHPGK0I6ZYp>NbcSGXvkys(o*mH!RixC7TkfE19wOa4V?m>_5vpy>vRuB^!WP`w@Lj zkoV)=1R;t9_*!&s11rOx&Sh;V?vs0d(Ar1#yG?g%B@(r-etEM0M6Bv7m2BbhlyMHD zoXf9&pZTWT7SaR0E_oY8oHg~Q5OC>So!6zc+n}RF&YBl^D_EyVsZ0lF>*3fy6#9>I zPyNG%P#^Eyi8UM|UGsjY*a|t&{+Rb)O|t%SSLm_densnjAL(rV!dZa)N@L&l--r!< z2uCiypemie$4ebA3Pi+hVYvnmE1|_7wmT-6LwW4ds5QBjE9S@~!;xI@a`-NqNTWag z!Fw_WBF{>zTo3bEDS6s(MXt@Mo$cEv-dabrDd|)&@Vd({N-!%Qt&O9=smi?eltN|W zv+58pGj^|%tfVDJ3$hOPzHlXM0mpgTk@kL7@;%n6K?cBlj3Iy@4UdmcM`7Ew9>6Yx z&oKD6J}em$IzGmSJpq9%t_oMUt}?-!*_{yCBHf~?a?^3mcz{F-Nd|T2!qvP=iu@UC z+5`7|*GIkv`hcRniPbz7xuZdS>T+4L+_@D*d(PsT$whRw^}XHfcXl}bQuFsm!B9t7-9Jcczd3XGOz1?FemyeM&#FQ#VSNS^T+DkzSQmb za|+R@0@4o=#4dyL555n2j`(4qyN5^m@!FSc22L-wvQJ>m;{)a9X4>GQU03rB00C_D z_!{(T<<3@p=gcVlXO*SvQ69xphUL`{zs>Sgiqh3c z;SN1x1c`9dy(>4Lp`@z>m55We2@UWiwit=i~Z04yzZc#cyD7J;;~emV^Uj{2a1z zRjQF^`mz9Ru5$D#r%m&!Wx6y8U?%)JXl$D=>`iQA%O@=Aq4CTc^`PIW2BUJ?ZSH!l zP|~hkMRo@|OSj!G1ROEluh3e8iS({)*`kBK=_Dspt4m<irrvzKt1yjhyg)Dvb*d&H`F1M5e0{a7w7)AIKdzU@fAz2g^07twC9vhkNDZh`%M z>FnP{$}RAp;U=UTD<2cS9d%Ot(M%G^cACz)8>6?g^fts-s%-|s5p_F~c{6Vcl%zLw z))1xJ@AR&Vg_}H=#nZdE+$$y@KGgjE5p9Jsesy2SRIyo$#=F4}UMh%~;505fso zDVi4jWDR66_TsF(;5j#J!plXsw6j^a{aYLr!msT^4wDE(#f9}ICUVW^vK4l(?&}9e7EP1f*8I;#rS;G()S0ve5s-SER+1G^6+5kdi_1b? zOh4JL^Dm#Yj&tq9rz5UDQJAo!ImAg78ZDdJSxaj6x8j%?B3w}*q8#nkME&<-XwOI! zMwbbFbk?{Nan)q_`pS}EAXaC>K57Oh)u?(uw5wF@im)t=^Mq{ND2Z*&Ylk*BPz^IB zyVA>XDUQ!bCN9oEJArH-9XHqFq-=fNUUNgA@IeG4cc&MNb8fD&QkK zJI18C_CTh;r2rDh<8vm7ugD)U$v1pG-}jg=BHlY;TPPvf?dyIPzV<@9<{xgU#@^$j-(u%f*4qYz5ig$NVCvVv zXYUTCR3f3&!HtV-AE-Nhk0NG(s6S$-UHzGE~rF4dj;*N2EQO0R&8@@OoFS zcA$qyDKS%E7U-MnpUR|eXpSlA&HGw!rUBNA-8y$QH<4@tV!d}+dDmf=U&^VOY%FPu zIr7`9@z=~anU&YCK^eeLr6(d)t-6F`_xSIlbpWy53EZ`lfC6#Ol(pR3M6P5ljoXj} z|C3(-uUZ})7qkgUxH-RuJ_5!q%P?0Ea`cJ4^E;+1&_l>A$v5G^x1K!zEqv~$IV&6( z_*L%C6{LY?+tl)52gXnL&HvR0f~YZ?>bssm<=H)(BRyvGUmk0GAsn)*j|Z5pls+4$ zzGWfIT9&j6YMSaU*j519r#g!0FmtHAlhkvSxn~1xajGH3JRihTFZ# z1GFAd*4Q-%B8Ic55kCuBGs={nXKJ}8j0&|?;#nxOhqap;9U;uB^OhlHkrGXPV)4*P z{54~jV@Wc|4G7VwQEv2ks29@c``zY+Sp(YypXm-)1?=;wao@y5mG&kR{tbVjYpl!V zj{A~dA0=w=N`wC6k*i3C2e0_XNjlx7ZheI7BW*$R5}m zLbJ(%gWsD;``b2k!HNIq0r43#d|LszcFMMz&9>MfsO16bgzM|}J82)M@USBFdT<|y z!Rb$*IEKiL%NiMOMZ|ytWvM6cg1FNIs<|LTVC)$mHbFF-IO%H5zO+`5Vf+#P&mp3j zr}s{!RfALJ8G5Pxmq~v$q0R^B7iYUs3mXKF?xrM@P|TDDIt5DC=JOppG>{B<1R!Oo z$?KAGNl`^@S+%Fo4W2VY=W4xL_gdFfj8px?ed6j-bF5Sx9&80k!;i-L@Xur5a*O%o zU;f5@QraYtH1H%ecGv6+6PT+3NWFvxJYAExxxW1PtBDt-p4gXUX#LQ(EEJM(7r29u zbme%WnFM0#1k<3@e;1pqLDZ|TjZx|dcqCHaT5BDy1a`pvE?l^Oy$q&DI3x=h;+e>|ilWkKJvq zH|ZNHGa!E(oRn4+*RlM1Hi6u(Hg<@()&~ABC<&1Zx;j$+9s#Nk7j;wS32u5|qL)xv zvl3J+k~{C~c?Xl!5AYQotRYgTth%}UN4a`-{6Vbi!wE*LOFwwjJfcFX2ZEC8{K*C* z+o~~7<{XYirq)LcJoxm7qCqx;#>PK80%l|VKA18uGHGIwi^srie(|6+xRRQqc|0ge z@JF8eH!coXal+3vC&z}ArU`Rt1s%gj6C9!LJrY zPFFnq{%;HNxvNj;6F3HBOukz+begBbaV~3Yr2J=lpqQOmCvFzwUj_!5+JP%{xhuX- zQaiWTOHCq}$9jVotPz9+nG_3AY@38H7MJq=%^7(>P~Cqt_#Om4))%#&u`ft@5)Gk5 zGtCT_?d?AFn%EOz{o(Tt2FPpLUabLcZ z5Du)J6z>KdF}d!i@bc))PF0q%fEiFyT9b5^15k0r$xF$DPue5+3ZSoi8DwUL>a;b=)9Re^LDiZ~s*h$3lnZ>@X<#QE^4^DoEdlX8wK`+HCo;+um9y7{5DFE%WfMGF{qFQ%_4V)|0xuzhmtSHbAQF ztHIa7{*Aiyy zF7YAHrjeo#}v(CMYU}Kvzr2rQUME1X~uRO9<6mx{O_t%&5&|b4@#~Nd}A6u zZaH@YZdmNMS^8rJi}wu+cZMfN`g~Fu(*tro3pE7h$hk%mAmg^L*;BpuLmwPle`*jH zSZ2M@M5`~x?YrUvDeBnH)<(pEJeUCM#nlV@p{YT-=*)k6LUdgsi0PMN{^|xB9Rd-C z+|d}Fs^_BsC5G>g*x{k!cKH_vdE*SyKTfI~u0D(zo&rpkYhZLjhdk8v&k6jml$P(Z zB!nAt9N##jOkb8usLt&Di>xj7%-}+%@kWwp8=3HARMvWMd`VQF3p=Yq-i22y-Z6#x zSVnOKCVA@00l20BaRgHMn@@lRG|%>?U*wI2c3v0+FsBY#$$8yqIx3*oUOZZgA>)tc z@!%t8ba-*vUvB|q@!@a}yXdbFc~Fo|K8T34ki+R)OuL4}mSEwj$Mjy1uys_J9=!S` z>DOIEE=1AG(5`0oDausA^dCU5#WuANd__)IwF8%*`_i=2(U0?V=<(1{_c)FXJu2NW zx${-{LbY>ydPAn{(ASL0qUe*tV(xK(z(os<%^;_ElehaM@Z+XeugpJgL$i%-_qWw1 z=jZc|VL3Ot(6W13)jO>u{7W~-VUvrurm@;2k`@mN6u1EU^2`{nWUeR|d5gN&Rn{um zuiMnl1Ta(EO4;w{`TJ_+b;8yUs{1UGOiDH{KLudBFAx8Fl{TeDJYmow)Kq|6@}|Y; zK261faH1f=AWL8d?Cg7NEFK*ch!8nxggo-QEu}%M{;%=pzlt&dKl=Wkf`i(I)#@6x z11Hq0`>?71a#{nQX)%yv6u1&Q7${zkxw-H8JadF}fMO=9(3T?}YY^U`HQ@hi)_`MS zHiz}$n^H_6u^WaD9WOx3zOgCQo$Vvdv)MWd0BWBr~W*cGyY18ui3 zU$UeC3w-Hy>R0GA8A0qDs9XM5q=*-ONpiOjG)~wW|%|LHZ%_1auOs@_b1nw;IZneBuFAnAp``qhl z)gwse5{HwcWR@KSFJ3*Xfhm<_Ayb-mJZmcF?BwCyj`8t`kES}FFEgIT!MnNl8+ys= z5v8+I+di5(qW>iN&Ff?Q<~pn@Ebb;vIw_#4wB2BMV(N$~dZ*U5ZF8~x^IvbKII}ku?%xOP3!i9`_P-IE z;=%JyYb-X0UXBD~#Y~{PSw^4x40_4a20YMlXPvywQ}^1QVb^|h)VG5q@8i>g5F_=R z+ayS>B_4fatL>Mua0~dfyKNk#{J=T!{R*O2|B34yue6KHMvV#lk#cA%)UMT!NgZx? zg@CoJ{KTY;d35Z5e_|+Z*VGu;aBj7!Zi`%A+9(amI&|sj)H4kJH z8Ka#1&lIHIm8!n#;a;wiuv`br;5z0orO655sd4GjhQfc_+mep#7KWcj`3yPgCX!vM z-oZyvX+H#uRw)Swjn`J354vZ3XbSJQq&g*rK=b$K(Ng$fLht#mK@PvZvTf04nFnS& zygL)y!|wW!ErAJeqsK@MQ{x`EFg?!wI1v`tjrXr>IqK8zJb4S881|oo)X3k6R*OZJ zZ}9Y{)a}dgm|j2L4OQShC}nACS_ z9|PSkQxCemo@MsjbIy>V_*mhF=)qq6C80momIm(TC*3I8+m6JMKkb!&Kb6}Pf;U@d zY1?e}ZdoP5I#tzW#=nI#eb?TLH6n5NW3d6P5OBJ3@ahi#^T}#&G^s5SbzS{A$Sia` z<_5=uD@HXh^>0ZMNuc{dCc4Gw4eD1^Mx|lMjTNL+XztfsNWa`>L6af(K1<_3@e*xD zEG1p+Vvc_^$_Ay2gqZqXIKy8@XLJj>cJt&t-CVd*HloY$awX6Xjc5gyG^~`*Em{e2T+ZnEn zZv1+Ft8IPh9vz&0%q>QkrJsPV-r!jz9)DWkYxcT^qPNw5`V_2&k7R zEWi+OI52+Gg&}{@8w-*3k#rJoUiDf`CDJvO-&jIp33h3kow@ySwN+VFJe}X2bZJD7 zqh_8ZFw+LhRwQ7v>cUdueBVrMkZTd4AxAkRmY8Xd#hjn0V`1riddMU!~YVRa81 zjlYnZ@7>t7DQsHPiZ}u9j#wFOdIuJEKa4(zV+? z?w#8lG!M@Egg`k!LJK(~dB7W3nC5Qt%U+TUy%Y>+8mHnV6|7h6I%E5Apr&W}qms}W zM1hNE{4LyGMbaFj- zkLDWuFn(O({TM*;xY`Vi0RJ!wMMTP{?4P^^^qG<_A?;{a?;p<`egh&~xikGfOJV>& z?VbX!^{4pl!JIYG#BzRtu>olsZbm+TPg#8Esp?%EGUAaA*P9098HA(Zgrv-pVZh!w zMO6O+Z186yr76a2<86psi9q_aa=)Zqh#-oMJXMbXST?>;!&r{X5^bUdSaYKvf5art z<0o#)S$5wQ$9UGhD3~h68qP%d1bSk~Mm{dPIebZRXX%FMsE9p-djsJL?g}ma@GSm= zw99nsq=naUM)2O8!%u(8yjZrsWV!d%;^7bTBdDYf@{AnxJe%6ZbG1upF|;?Y=>h4J zdsa!Q13fpw!Tr=?QTzG|Oocv}`JeE%+~|E=itt`m2X64qo3s4yS5Ffzn z9=cIpd4l+l@qx=@;P>7T%b-b1C#U4Bs}<+`MnGoAj!L*0bRoxcmDUnLW?O5 z`tBEl1Nn#o(|!jRnCm1V@fbh2*bl@54bCyg`yq;K**4|#w}A-Xj>PIlvgYmv#|%%o z@A{2@4%sq{7d}>s9y!LJwRp;j+u^<29RGGCH4v;pN>;1;8%-7mJoEfyh-;zG!m@A& zo`Z;NrH^0z{`zS(rT_C0LZM)0I`t8_>lyPg=P5%$%Av|X_nN55Qr9}{M6-7zM%{vp zDdXm3S5vw{5%u&l!O9pzyH_|@S{~3%7RQy%O(yZ-V3tJxY%ldQOQ&8%@|X;!m^ON& zXMMB_Sm9rcKmu-m{33}8{LIeRd(KnoX?2ALnuNcyaycMX2C6)kl}7nq`JhEpzG zFKgaL48#X_uu|1A!5?Ad)dDOVC^h;YFK&aII-fedh>F6`Y?@RVOH__KwwQ64FIt7q zInBP8LT8Z_d&fhZMZoycN$u6Yfy@x{3%ec&@@J-?B=9W7{iI}9qLr|vX;14{0Qh3*-d0A>>k1OB;L%hNA8!#-(#MBiYZ9M!J$z5la?1_~2 zV5&Rq_I8+BcZq|XHn9f&UerXC!u=)YYhS6c5nsfh`a}?}OpK(+J|evW1nOzQ{GX(! zyx|Epe_~e6R{bH_E-2v`i@E-H<6GgZwK|InENd_J(mNxT++an#C&J&Cbpc*56 z-uJ>Ed!6oVJX=aGmHnvHC8QweN9Fp{THKG4Sn`mZl_8cQkj_J!NoO6taIy({D4eM*HnY+T{|kD=o;iu&@%YZ#9P35TRF<1nB*#BM z;n8OqY}K=%ADHN8Zq~7Ms{}n(pI!u(#u|TsD3{_i))mwjZWRD@m;OmU6p~v;RXknw zhQ}bJxXUOSND61b$TKAS43pq<0QT`9nduX_6k4_~@-Si?KS$#xl+#@oFR)*;=xXi! z`>&^MTaX^Opd6IRRUIbxu;YSD9@uiFO)NgS?C zIIYGrfDl;1??R+-7)GW7S0#5A|3Srgl{BDjwxZ{+e=aMP|!^9>0LA-&cue z15&>M-fb``(RSQn+m4ZM_Zp=wPA$!Y+un~@_Y={Vh>H1Sv%$K%Q>U6*zxTSXd*sj> z33!IQK?Mw}^Gs073^C7m`wDD@sT$L(+-o_1TXZ&v4q`Lj84<<7(1Q@tDX`otg9OaMg#yUjQ zvadbXIhL}PB#boHoBMx^YAEnH=}G=T-q#_Nt^$mf4>~SoE(}XmX0L+TQETHH|8Ke> zY-3YnjsmWrKviyx#m~nIJ6BLCG2myk#~NHOU=1D{*LNT7PDTLZE3fZ0$z_YqyclqU zWiTu1sC9zYe-pCzAGULk3jYTR-!GzEzWg^BxxdF?Huzlw7u;`tAMSKI-})^3pf98j z!>?&b0nV&|_Y%i`i(hgSZSK7@e0Pr(O_$YVs2DARb41$i_`T{Si?h5$`W;8ko&~wY zhEcmV3-G@&j)8pH2pkmc(V=JqV{#F5oH4ifrmf4`sG% z438qWYEoOGnvI>rni1LCczJ@iHN;MUh@qoRfe=xE&Y4MD?@TxB=XkRB^pEA2Av$HY zO!`>#rYcK?&_5#*7!MXdXW*McvU7lC;in{=?|1zV8Cs)*u>pn}%9da0bg-@QCD+t- zr$DMBZDz%WWOm1qnU`rUD>`$kK9@FsMFi6E5)JFe-2eIhbQMe4&*skw<=~imlFEwryD=NwAm@#_d|u<8CbBSb zMG;e{(1#bqQg?^ky^kRYey%{EP+c+1vJG5~UTt1;6V?;XW^RGlMy0STHLvG2XQ<8? zUt{l!hQ8uQBf13dt zrD*lUj)M;4`S`}}jBMGRWcoKtsP*oyc{P>s-o*&E#t48 zx*uNCQL61T#r7mr2uoXxO%2ezje4~pW-0J!?t*h}7Fg^+!1pG{ToWXt%_{gTYang{ zLt{2m+t!hP)JpPWDkxW~eBTV(0UA?t|k zbo8gdCD&;nwD0xFc!6TAvubHJl=AS`aer()zP!siEhJz3w_ofShCbbR_eX3du0ScCAl4(&;)hEVO7xTU&-pU~Sx?uEa{VnPnqdC*J;Z3J>8 z<9F}PRvR8_mOp2>08bjBm`^CN;h!16G*Ky+YwYmaaxMK3=0)E{6YzJ=Ag3#L5^hk; zN&@rT5KKD2d&qru`TFHNpGwLW{+zNdUH>)GFWGn2p!uZ0R#&Fvr2;M4Be>O)7j0M> zQn{x_`SkEJ%@GgpFI4^DH&@#Y)!`!8X`ffY+3e&S&V2dASr!9MG`|52o_nFinbLN~ zZ+^ldIy#Y0KKdRFoty(2`rluda5Y$KwDcPuTD&6Ktq9UIy_R?Odt1AyC7bFw2{jxj zzT2#PLAvoHX6LKwTkZv0*~UD^oN5b?N#Au%VWczWq;VnVpdSBR>tOe0o@j2xcEX{o zT7M%K2m9{F4wJ>ohZt4|rJz7jrhBFqi@V+gDH*|B^XRu1Ba|!ylFrrKgU5=F9OXLH z@M+|E zR)~W~G8V=0F+tOULA&IcDE+Dgrlb84<>f9U&UAxdl_BcUK}Ag+Nf&Z6?_12PVF}Yo zi;mu2p|4-%v5PN#i221WM$o;rMl=`pqJ zS@3a951NV{m>ysp2L^6e2GoUNFEE9;Ia@@zr)^2|Cm`aVWNWb8=e;PhW>vX_K2P^e zOenBXcwQ?auOt^}Q&tJwWP2{e( zZ>CBg-SMVn67BWa5B#tx0q63XWFlRs6Rt0^(-#@0^waTjn3^D0lvOkMZ9%@@(XVB%Y=x1SOxR6Cjyi) zA&^)86C?a5!d0E%p|nRs`cI!kKEvGQxeyE18dsP)5hn)s7~We^zLo%fu?aNKhrhAN zeJ5s)nk?6vQ=v(XL4%0XMQa?$Q8QF5ZclOlQlXFiui^#mQye?s$r z9oO7SkU)P%Gt+M1ybtoZ`MSR-pq)}|v*JtIB`v@B7JDc#T`hsmbnC`4u}P<@Kkk!| zUmsJq>qoo@`?AcfdjnQhZ&{{HL@XL6_oUQvda)1U^0MJv`rU~b^W+)Ta8AR{^%EA- z!E#(Zn@Sf%t>Pd0QgelAnS7E3Mo*Yw?69)UFTshAWD3}2?2R`e!<(#+RN6k4%-{PL z^+h?e2>^jFJ&FBB;QG)|&&=&tV}NeXHw$Wj&15>yy>iZ)Bo{Czs0*5i3~_UAeGPyh zr-30VI!;u6cTeKi{A#7R`|L;J&}803YxmWcFbWJ5cV`8KPI1(;jh8~it49CdHt}!3 z?%Ctr`%E+q20$BiHo|`)CL@N}!Oie3w+_GS|860rhW(by%sVy@~$7QIsSwRTL9e&2W)QVi&O4{!+DfNR{mN6SX5H zmZ1}lovlQ$^YCrE*E(E*tz%3EA-2&*&i|_Fx4mjryv(?d2u#!Q@R=UYhJG-=*Gp#p?L8v5P7LEZ5PBQ!xq{S}I}gnyn%iq~-#b)i{K3E_4_&BN@E!6u;cA%Je`UJ; zU?_#12KY#CoT{*-wYB7}p?vfn&D( zLIVD?12f%l3XJ?%J|w=>*~P`kU3c|EsQZX-q>(~gGUO=+dPl@S*qV|q)nyq6yhW5Z z%*~W|KhHOB4uP=fRFCBhz#71$Vi?VrF3X6#*^0H5%{Oacb9MCH!a8j8TdGvi9Y=<` zpaoi3Xi{JRXOVqfCalPq(s!* z)kbCf1S?1UwKeok!2+Hgj$*pWXwjLi#NxHKo^zudC)OHZliyxA^@{ zKcv^o@rQq6uztY5Fe*XzOg^I>M;MBmQ4aUSk^_kNRzGDShOAM(2EUtyoQG9c-og9H z{#8_q7&_3(E6Y_}17@qTzVSu`jm>mg+HFcp!ZLLr9nal3O>{W=}V zL5`_M$_&&3+7C0GcKvba=1dt&qC~3xCN1Q1malo zyjIyZZkUCXG+@!Lm@+>RF2}6gvk8;{)Xmn zzyfNSX8&oK%<+bHEp1;kDtp_fv_U}9e9T&^&Y#$8?w%!yF^ex0xVBfZbJKRqq4I7} zyN@pOgaN|Ac&DHaCM2#xc;J=2M+fuOf9L*(`whr{Yy|KQ3H)Px0y(4Ytl6oLIqg#K zgj{#*4BvG_V&nch_#qG!38h?`c$V2VZ(jpin^cJ&>wA z{>zw3q^Qa>;bY7Y>I1p@$MI~_3;isgF+-5(M2QQykIH_LjE{7-lEt1zXZrhA>MN#z zte_PK<11K-9B!?x=I%7tdgQwEko*QVG}4+#bBy9&Un`NJ(7zIQPlM(Q`|JmAe`mHh z)G!mtOBePZh==ZD_x3QFVBF|8+6t?L6w=biXko`fuDy=XzMw91-pfleq1LBTz0z;R zt(LuauW?3#wwz;f%eX8kfH2Pt!EtFqkRMtk@$3pz%b&pkwQ*9g zw71%0s@w1;IO>+dE6QCNz70e`I58ah4y21$D?QYq)WAJ%}Y(^F%?Vw{dr563T3nz9MV}$?%x6$empj>Rf*JD=B3?Qlr z%(b@@BJx}6C#3RtKJOF`DHMtoWa|lcwsj9ixW|8`2W_Ia92*}3DmvK@e3V-bq446i zw}_}M&}+7g4;shG*BY8GTbjB{VdFqtT03-fKv+Je@9)A6|JGIZl`mcN`nVrb=5%Bi zrHHYF2yU;RwfF^cJWO}|^Y}A1Oym33ivnGJi7kAbuh&2Nt2SmuZ)y&QD6NRLA2#;* zw!S;XN)f7dq)>9pB`7-2#CpAcz2jL)LY4Z>J-z=OWMhyXpD;-`vw{z%H8t1Oex02p zBXq{G@b}hMY1r>Ekuspm+TB3QDsznCS6e zCc$;6pTu&Wd5m|Y=lZSk)4YT$QEjA*Vgx)zPb-%Woj z_tr!}>vFw@mr6&zT@10=U2N!NE_3(_;tBt`fVl;Y@wfNfNx?V zA?XWK8;^s0Tw+8yDL!_(HU$Y(&h@@=l^#K1Hdf`w9z+PJ34NrjM+>ur6}vRYsKhe~ zr2s^jWW2U5rBw(DbI+*G-fPOjAEC*DFDAxXl=)nvHDqKwyONF<)PC)+_etl92SlDz zcWR$oyJVAv5j51|P`sqtc=Sspl`P4i=wYv%T4oZW6B0Y3_%~RE36_)HdnF6Xh;TzXy)!KAocaoA|kr4h@q}@_I z!M7yg~;(Z^)>p3e5=YEdD?|iw7x{|^-ZO35^tuE;?F( z1FjBpm$Fb0bWFBXI>j59oL?Yt=7R&dD@^nKK%`ZjaBhs)S?wCudvm<9O3tb|hZ4K`rlPLVyOhvHu}HE5ws!;8HWcF~ zwliNLzIVsyiIZdNXBg*YF3gmN189cTs7WPn!2RzS@MYuIn&n{;(?y6}!zmMi6>F6b zr%UX^rs*>(o=uWj1xyD&r_Gk!?b+!cZ8q|NiO_MdJpA*?_%(nTY;exC3Ek+c{y#K* zWmwa1ptgY`(xNm>L<#9`CL$pHr$I_ULApC8(%l^cL6DXXfzhK8kZuNyW+MlT{a!rh zyq|V$*YkPL{oF~d%T$_`ht%iKBg=gR^m7{LcE1b^KPU$d%;;06{wnKl#^*G=4`Bw5 zl7UwnCu~+h`r#iEzg}iwNy0Yr;gl(|w@t*sOYek^A%(KZSOTab13>GRg9%IcnkDIA zPH|FO9=)0)C?>}7;C{@)e=pRvG)K9{y7S{{71>w5Peza@e>&o~bqSlkEwGGE-6-QT z>3-kBT8*!6GIWQ$#y6YAu!PX~L*jLcab@EG&$!^3Lblm7*Yz{^4+U)RL;N=^9+qJ+ zj5C&=F^lqt8l}!DII0G+K0L`#)i$$&M8N97%MQ}b2EP;Q4G3QAQ#N)fU}g*TGT7$N zDp}k?g75x3eQ(eZ73~L=Z%ff}tZ!y3C4<3NL=)3O`)pP-c-F9@F`aA!NV}tS9P;nf9DFz7Y1+GCdz#%kF zt|D)h7P{g;>8@|SJqlce0{6p!&FhZaIne+b;oE;zf*T3b1?M>U3e7EF z1FHR(H39&!+gydu6!0nbA2$1+LK*R!J`7}v?vJrk>RDa&Zje8tc)(!%LxaXMr+Qd- zRb*CO!m0LFeC?N3rnEaL>JCE&MLzGr-)JT#oH$DpRde2bk^*e)g`q+Dqk4_$j%dM4 z9T4Nmbb}4T;>O|XcVg9V9Xgm2_q4D0viYw2Ch}5kMN3hqdncBjB}#J@7sAajakcU8D{X1C#m}1Iom}%fJERxTg}c%DrOw>p zYX~6{e=IGB@p3f5m%-@IzcYVhs9mY{*b8~7`skzX7&b2CoBy?62G<^l<;Ffxaddc^ zEa=gGxyXlXHz#AZ=oX7YFCIT?^t|4qZ`axBqgbqpYa6s^+~RO8a2=1X^)8QWWE`Ss zoTE#2QK4%b$_fkTFrs1?j!N#Ok$odz%@efwTT0L#?V90ULVxraroxQn^fALe%RHz5`hR-QuLgY7X2XJaXLX zqS6SgXUHsolOV=VFzzr^KAd@5|{XKN2U644JdX&Q#l){3l#8r{gdR z7e-qAVC1?c03!8Jiroezty}$y3dvc8j?7hAe} zPG;<+2T_$4wJLuLm{~ZhRroH4Bq}bFM(tZI@k{`l_v``c4$gl+mZ?u?bV!N&({Xhs zNmUjww7C4x7Mpe_7ZoRVP6ZXCEF+eTJ+(BwBeKto{C+=wmD{3f|L{_~+ckmibJ7ob z>`)+%#sv`2zc6z4!>> zC;Qy=W7+Mdfs95|{_V-)c7E-bgevB} z_?1;Jz4MZv(JQ=Jd$72g^vH&p3zTJ>K>v6B-K{FzXEKV7$BOZEuWw5Nh5jnzGJp{J(vaVh8jQDCx=!GB3$ zTNrCCs?LG8o;Y+@O}sVuRJ>GopB73Hl(PkwdS`c$1mIH0k*7@NSUZ&Zowx=E1Ggw?B_ zl=Q!SMx4D|}GYd?)P0pqCf`nOtM?&u-HM%s7pYN&}Y&uSGiN0m* zH=dgpau`fFhe9|4FKPkPk85mwK2#qOy+dZ8|cPpfBV zweW|dPh{z%ql&5oSwu@>cjSO##>Z^cP*!@tp5z&SK+D4YI@EDLK-bpU&RdCSY?Y@) zWpUn9zx{&y%6OwiO04!wtw!j@)PtxdIzlu94C;?%zud}#1S(W_q>T~d9R*++15o3> zMK+DhYo^&&@0wDHRc_PawJOeZ`9IA&l4_cszX~bh2#0+YcSstF%Zb8IaIQeUvx?@r zyp!=*`s~z>#`^u5UYg~B zuZ&ZkZ=DtZJYd`%;9v&a;UWP3*{e};`I!M3&EO?{ZY%y?#X6&psxQU)Ipi{ zho*ak*lRsFxan{k117!lzGsOIi!@xby3kuS{m$Ng-pl~?|Gin&Ddkn|_^&}`%%o89 zzukC0i<(~iq~Oh+YVhuuF8pu9e^y_(vjRgQ3%*1)j>Zpd>T)S!@nyeU4D#ybK>GjK z@MIiADxQhMU+>(SfRjdZlLU&%o5au6+?f*|Dt?@Zx|+z^qX3jJq>qhPP3wE#>f>cY z1$yCMA9y)ziIRt3QVJJcfeY}>QVSF~!+9Pf--KhVG3wNNcz@%cXc*4AU;8jBeehq$ z9=Q;#f!ON32Y|%rN=XUCLm|fy-TD{`pIOJ-w2YFN6= zdwa>Zdz7>zVtpf_det5tq^s^@6S~8|*LyON)FVDH~UCeq0I>t^kcQW$1G`$p1DcI)~{|$3x~uQ^p`vc<9euv?(`rKD{tj=9d3xD z|Ck>C1j%fgCRx|@y*@5XxmWa{cA);$6x|&HWG#RMa4P{6$0DXu%RP!$bLS_fgg7MZ zjp=R(K*xXEaeJGai2*nOzg^2%JZ!-dRK1U-eQt4peK{dui@wc4dte}li0rc& zLr1(-V&K+C83_9gN8p2QEwNqTgBBEI6Jmt9un=*J8v8%&&#71~P2wNImwU)R-%y;YUv)$F$C;Ug>lWsJAY;n)1eD z_|BwCNxT=Z2_A#;y6R+en`MVFn1i7mDBH$AN2_R7g~k#)<{U62A~$9kmRZ*%o`E>j zWu$ib3{&~?EKO~$luh!jZgl`XeMXSx!vzR4D2fIKntYjkpT~Y=a9Q%>WJ@=6l62^_nJ6Xx-=KtEylB0AYUS?$Rc=M{Sx#CHY@_! z%Z`~Ra1l}`&*5BNvDjF45BPHvQf+28gKPcP6${T)5qnMV?=#BXmCbLa-MP+85QL4g z)}(`tRe?aeqSHky7~wPSX;$?tSMS7=qyn+j1zV^x_q0w5yIlx1mzI=D=ln_>8O6j~#4xEU}S$6#aCTtDF0QmZ={wYJp(IB9_ zz(ovt%=sxbag49RtTnFt67p)S>=-gOg8dIKP5zAXLi#HtuArB`I48kx&_(MwW1R&~ zf6wd2l-n*bJ72&ok;Dk4P+2qj7t>`Nip!YKH#TrxqIsy7FSQc?rk{)1bSt> zN)&%VpxqYzXqCG?qxn8LRX9HELX<2dw57|n&;I_tx)@LGS=2HAk6!J zx0(J-Qi$m_x*L$ebeZQ8lxBS4E#L4(Cd!WP1M)hXbWSp;bQO$m+lzO`Q0)<9(dpU| zQvIzbr*AMCa)boxKvo}#81s;1hGR3sIbbd$De zM4n%%$1~Fs?Eyl5x@-B7@JCdAFX1NykK|c(0^%MlWYu(zeQ%r%eEABaHhKid*nl` zGu%nr{r9;S(@d4r#ER#{>7kcxrg)=98Y19)_5?p#3%spAd)#7(FV+tt)5i;);|SD( zxRWB8#2(adwP$|u>P-UsqCIzr^(WPZ!@N$2gyS5Z194Jc?B zYzUIfem|-jeXyh4=F-_Lmu0_p`2pS-2;hQ1YkKO^r*pY%*Tl^cKuDCM za}O8~;Ko>0%A^dvWLH2c_86cewMv_3XbaUU9gj5sW%F1=DU&P+OIj=<*O9VoHp-MKBN|* zGJd`y=amfYmm9;2S%>V?@vCH0^6?`JOH-!FC5eGItZSjG173gSP5@yX$Rk{aOkv?F5e+yoO!eDUJTP7p zJW5loDRQt~{|N85Gcy6ZyC4A9LTb1dr}%ZMyOY$T2A=k{c4axm7|l8SqP&D`kMG_m z*44Jl%E+x#QZ>4S&4_s06yRk9=3OR0d#XMwJF=)PM5$R@2D+H1IF|^Q@4eR1_*GGj zD+a%7jr^e|w09S9aWJN2UiNJ6C8MSNv-lTz>kz91#ze##k;G!6;&2T;S8!&*R)ve} zMBSEigN6j3CV!v0TY{$G{Vwm)O5;BkHHEK7zi#Yj7o6GzSMlfe<0oCWX0Mr^H{P)e zD81o6pBW1SC2rB1G)Pnc4}fz2Cx8}iCVl@d6+Fn0nl9b^71t2+l&-&dk})BqiJ|Q0 z;$%~oF?WVaHTya0S4dwJbl}Lvi;+h@SxNG=}%247?(7#EOK*5n<$&tw1?hcM>QVVt1C4U0)jjL z6eY+TEVxzT0dP3OaMa4>@~#TW^A&>8>*kRr^Zf@@Zq=+BObReX^}i4Wh9Wh>z?Gq2 z8M}&^HMi}{lUS`qigQkVf5e2wJpbaV=7AL%Lp#nT9vAsvs6bdwh8iQ!(#~OgfHy2O zUtMa;-=4HRGko8US)+EPxOVEjo|WtJK2xEKFp_>!V(d!8Qn}YriN$5HK@2`~KQT(Thiv_RPh`JOH?YQOLL0X#IvVJvZXWO2#wk2%=jymm z$&}XiQaHAHYl7;Jcqv?FtX$!D!#p9Jdgr99ygMKpG$nlS_abLA>YqMN9(!0WNC zbn~iTMi!0qk}>3y1fc&`^*X>Tufb93DrC*1KtIQ;L;;6>#wzdpI~T4R2(!g$YiZp{ z1w-^mhMJWa?kPZ4S=$Bqz|rA{N*fclS`fgdRb+b)`}gBk8L_`JVGEtCSh_*sFzT2Y z3byQi&rnDk@As3x+XAL8@+pqr6zBJ!hf!C>rYxObib!y+adggbl^>q4z}7nSqDwm2 zqsL<*Q^xiWY3M}Z5PCNIBEDwz%)I7i8!{{J2wN%)0_5;c3+-txX|Ipd)(u^p((`%B0qv%$nb#?cBpN?@!^F zx50!8ruQJqO!{f0XOCsOx6p3wHO2u^RQU&js)u1j#3}H;@43C2NaH8d>IE7jb9VpX zHk@Asi*Sa=FKt?@9|`g?`#jdRZS+e`%9k;8J_b@rp}hcdJ|@#Jr%EYMMd3C}+`sPFW8h8ZWKb9B zz~?-FT*^&Q_T!e%Ua+duFXLgh_DriC+i{;YZj`{S+6Sh~PZAZwR$RxG1vd0)kbayLKKf(9dacd70^AiNH_n+y#TA0rzY3n_@>hd*- z*-AU1#>Z{~dNtiR{Q5FnojUUKxslcwU z4^CJyN3ewAyr{YJc{j6?q|uEyipO-ZI|@u1Id&3Tzn|x?2ct`)^!YY{bXIB(QJ5&N ze>ZlJiuAsMJ_$DKBUw@XA0k`r#7aztEo<*Xryf8LOnSYGY!xB3a8Q2(6hoyulB}G& z9(96u!=yu_cQSs(;Z?$g#df*1pB-I;Jt$|sL3%YAM_ZmD1w}V*Evrn;1J7^Q377OP z3Ef98R|Fa~1M+?))4!v%rV1ZC{OQNr6^{OPti}HW5zQK;tYGxRE)wux{Japmk%oW^tz2=+q6Wj!%?~D!I zw}XupT>AFif~NpdTybWka}Eaoym-oYN>gWHZ!^gf-?914Jm?#pA~n9se_I=j(>57^ zkk-kq^0uGG5;B0vOwmsDe=Bi4{@I>IQ>6Yn4r|FEIP#d4?rV4Rmmb2G2Qz+=kP5&y zJx@iVKcHVCAOHtxKu3Rmt!l=~qGZr&vGb9&3S_R?IKYZuo*hAXGDn>8_prD5*ZBtZ zPw@AH3}VyL-`8_TkXZ01sSN;o@PY*zeYHZ0^i^2VvCBpR7`vRK*EhKvfTH}FMy>De zgAPlls2k{sH;?ceJjwx6AMClA(3Pq3FA@TSXxJxc^3;6GaHjhjUS^USyX9Uul) z|Epn?2)IK(*^6xJ|EFaf?Rl_JN5BjPpbqQSf18H2olHlH{mrdHZ)~dX|2uVk+i82d zKmeHf^&ae*zW41F3g$Zp-~2@(Os9VY{nJ%oOp_tEw8;OYW&Q~wXscKNounb=K?p41 zWPiKf0$!5@LzhK6(>J2go4B1|jNk$3v3RWb^^Ge%uXW>=4bv-< z@Nv!>a9i|&CJ^{om0=`vg5dX4*UzwoKVOP6qA%`awosV1Ta=2LxL}sSaW&Cx1#p^$+PQ zb|8Kx6TIyAjZXh-wuh7+Tlk|IdzO+UR;0bx$nkSsY=~0)6Amn6>GgS}lB$TF*-o^J zMmJZPzk$D>U!uBvabpPi7U2@tBNOL*OZpjB8z0N~Z54lJKA4EL9_?^m2Kz)ok@bm4&UQ)ft#4%{O-R}96RnqRM zf-|_hM?c-x9{1=zIO{^HVha$E)K`dffc<=%>Nph2!K?5PIV;`P#w86A9e8#Qpu}9z zm&;b{yaGT&%UkE4CoJlLQ9o#Tpa`&+Ll^ihGExdWYrBOPGp5%C7RTwtIGvCKe@i&s zA|V$J#ZFjqK*Y^rLG&h&ovL?>FC$_uDo;X}GD%B@G~16_f}B`BF_LXAOrrh7pYbec0b^H;C#b%Q)17Bzfh%#mQ0O1Ya%rLx@r?)k5*)PlRRva zIVho(5)xI83GNcC%#<#$^RP6fKUSD4*t9qb&?ce9S0e1Ax5z-UWP7eO{&^~l4%r|u z=@P6~`-l$LDulcX3{AQTJ7MAH7VsFkILOn(7hhrJiR|8bj+VnLr*%BPY?S12uDlZKBQhc-e>PD-L~TTln59%r4R(yKeou;_)5e~ z=;lRcuOg>bz|_!NL|!930h9D@-vr!TJ4u9PEL)9de6+>8wDqv=OZ8v&Gm>~U!hr4h?>Aj0JHtG% z=dla;#;Gl}E(P9?>f#u zyqD{Cz-BUqB2@H?u2s8SsdY7tOvwO?p{ukqh7mGns$Sceq6 zIS{-KGEU2@NEwx9q?!lL=}a3Pr7L@pEHry1;BE+jy1rg_jlvT`fPay7>hT>U0!(H- z-zzPc7UR%=osSgWuxeEtucxHTS%oN@$DHiduJ=ny&ZW)0SoMXVtYmjZYw za1n1Gnv8-;{LV&h5|Cc~n%xzCwMu?Rj>12VNI219zg=H0(8jp_@Pok|k}9T1s*et5 ztr(^HY|r!9yr0>S6jv~r_pFDb^VT~&QBnm>Hb2OrcxeZF(H8|}tKePvq4!i+L$Ik) z;nz0@(yi3!G0Aj{NGRR=lL&zKR}q(@YzX8f5ko{GDiV3dc0Ew_6^a!Xv`0GRuGDW%X3Zd{Mv%eSXaT z;qnc`_k&$qW6XQFqw%Kl$;;(_V3pJW59l`)mm7JBfj`eXt+MJ&7Y_xs`Nej@wt(_m zR$;9_QneFU0`r)(qKJN`|Fk4AP%-!KDJZd{x#j{4EoXjKsQReB_Q()o;B38Hh%ZsG z>~eD#=q}^q^xEA_7^___(`Lb#;sLteBz0UL6CeI%VXS`}I>fKrW2F&~-oEp4lY1In zB?4u`D%>L_sY$vr{o`K_L_k>g@qnf(TpAWyNee_{Z=tb#<|9{b=5^K;7QaZC53Y*; z70sAom%2_)Gl>p)E^f8z-ojp(^$z}<6ah4at0il$s@Yn~!>55~cc`_Ro^cX`JNC zPhVS7_c+59RtB7eVHYM)VMz^5t%WVOzje*$>}C zhlSjJtm$picnI2tg2p)iOBI7C0RW@5YPzgG_langr+poBPG$Y~A9mvTXDvB~&E7_f z{@3#RdlXWMfuykJjh(1;`q^1r{#Ynpc|u!ni=-DwR)c%jjMSkqbJcn&u5p5};<$bt z7t!0PbC&p=i#A6(1ddyHOA?Xt7Q4_Gq*eogFG`6oAsf>c)^pFb%Igl=Eub!YCy`@8 zm?`chHCoX92Bp#}^Q6;)`1DbOlPQb>G>!hXskzbS>tos~g2&IE6rZPG3r}S8N-cbX z!sA_Yd&}pG)+-SWLxQy0QWhczuf{#`x%M4r2Z~K4MYV)h0jRq8wzQr#oFgm^1ln6v zI21z%u0m#uhQ=E!O#yljWq|&S2C=fWDGi(U6e8>rxDzn!9m9HOEyvl<&=2<~7Pr*mXq%o}@lB7QaL%IxUAt9JqimcuYJV{oS;HRt zA!oDkYK{qNI}Gyw<1Zto(A_+yNTf{9h;@uCkj8N;XmKiCOww|cTx~n%P;ni;dYCoJ z>Qg8+g^S!{VHb~67ayIqp}%;IQOKQeH~!;xnBJf@Jaz)LFGh=LE%gvo(N0Dl36Lz7 zqvmFaNcY+PPH)Yq(;ERIxx6lzpXVv!OZ11a9B@nA2IRxWyjbh=Z4}bwh~iZ zDH=Gh83eMC=yZv2&5hF@?OWjMTMQFB%l>_K2W~aI(gB-nL}HF=?&1T}Z+PI~S4jhz zM%J%O2(2XPQ84gL>3-b6GC#6-2r$n*aE~0Xr7v_rOJyoJ4Tq%*)3sleFkg%`NG@!p zOVDTm$RXyFqweSxO*QrO%{Rr2%z(x~rb#E%EG@l=) z?#jvG=bY8b<;U8`@Sl5fq-J}MTogSrFiLJ3m1qmvxBLGgQ@`-dtmAhaT!H@EXmOHX zM=)YJFnw%3%Pi-AGVZa}8IJCJme>?p?SF7!G!o+N)}bgI8$<&v_*IiQ`NCM>yY%@N zE?vI)&v~k;BAB3mVk5(}WF3IYJ!0u_iq0Ma==@;p^0)6j1M&5Lfl6z`;DhCwq%xQa z6wjEoz&h=8z%1O^%m?6u;n#*Tn&r2%6O{d8EAAC4W|BQvPKimc?oQWX?oSe6RwDNM zAof$wc%ieEr9QJye@# zP8-yY`vVsLnJRHBOL2Xsp}&28cO~U|jb)~$zV;l5blIQ`uu8UvBwaJM`y>fVxa;b_We;AN5(tPqP->%r0a%M7R7a9F8Cl z8%6ciOb5j_3@j=;oXaQ47Pe|NDs!rx$y(_W2cACYm#Or$InVO1<5pfEnv#(D4nKSM zE|F4_Dp!e#&&-^0UL9qsQGGBE>dQP%V^7z5+o4NgUaG-6PWjw zMfjW!LwbD`D9}rFg4{S+UsnvHWFB?Xcd_f^_l!bOT+%|r2P$mH0=zRQCeO#&hp2{4 z8J|wqJRG`W^EdLmyV7D$2zr*bqc{IG(Px^Z`lqsMkc=&>&~_hFwnR+z3+G41HO==^c({Sq23tXMo8=J{450J z57`|n$VMt%=ep82`X~O(mVky_zD)gXvTN8o7H|J9*rL>0rcz$2$a4dm z2>vQw%+vC1O~_J9i~R__ZGD&5-1PthEK@PA)`w{bd<#546d7ONJ2va}KfJ-&EKs=F zWA}R)`@Ws2Mjo&u(Qa;>a}K_bTY9x7Z$JHy3QX7GP;AQ@Z0g(ue9os)go?vV^#nsy z5E(|uKhB@m<&8OB=R6x2%DK7rj!ESRw^OA-MEn&&S6!BEB3Y7?g%SW;Lagf{x!-Rm zD8#n+x9PrXVo3u6jG;jd#g#iq>%iy4cRI=wV-$Dl_9(q?I#mB$nW8{WzjTB0)`u%Cjt{)3IWPeg4c2r7DN7rti`{ya&MOxS51|K zCS>N0iGZSm#FuAG{JS=aHmPm`14cDf<6%NkA&S$o@5V!EA(|_`!D))w$=qdxy^bfG zCloT@Qw_^NdEO!FuLpwT49|dQVCOG}6EMUUW2(M>H;Yq`6I&=ewaK>6D0J}Dh3x2` z;T|QjdA1}@Kpm4C$sf*OA>6cx5qd5!3;Gy?3dNVXavqBXJ}c$yyi0|9;Sh>DX~cwa zi(p!YX0wJlnKX8H&J;b9 zvq;n`b+_S7CKK7)b7~GXFoORyl#5jO@Yy0;!^i)Kq8tft7t|~ndLI7MOQOm{j{@2# zL8bduU8>!U-)_=c)ZsivUEd~ny*N#R9EVzex!ZuW2=Z3XixGqrkn%o*pZY`)Q z1i(?iIJ$zTh0WOe5+4k^_JuC}Z}UBD)OGV#yxH#-`CnNEIO%~%Ywj10sJ?PrxI%wo zTkvx19uo^&lDJ#M?h@;LdtNzU3EY^m*~+f@;IcV4KzN1Nd%JGBaRC|7y#HKbUwW{2 zjIZ6|6mg3cj>fKYRUkD(^L8yjd(*m6@$tO(f_H58&|{*Cf%3FON|R1Nq-VvSY@qy8 zt#H^q!DV_l)1j(+NdY^!b&ek?zaw|3+`8#I)F5jT^SKj_m8SSMrpUTU?RDZU8m(wXoe)<708SLBN0erIndpOcu7- z&@EjriXLqn^;|y6@9gT79|@8sf)4q$P3M)XyAu}W!Yqe!;}fcBKd|L0|C-Q=RewMo zeCG+i_5HmY&h&;BnHbYxZKfutQLXBdUv)hJ`yy+EW&G}t zt;bPv5-uv}Q7>S+0pph->b`*olJ=DJWtwepQJ(i7M30OeK5#bG$>`p)QKnx>YiAf0 zibFYX?K9`bQ6Rx1_^-8Q$Pr-)fk}djeoh1Tg?pLBULps@j5eNqIIUDqblKNx=ba45 zZLN4JFi+k09pAQkYhYncyh-LbfdOH9W8736pyd#L|18-{v(n&Rk^Vq!of%nqandYNSJtQA5I3{giWA8XPW*hj@YbGFx{-ja7OHiFE8R88Ekry@+wJ$L$M!b7 z-oN(juWt%0pPDkqE#Sp+QlZml%uB0|TGt~Wp)O?eO-`JPvZ5t&t$HcnvTkHe{uZCN zFT@d2vwY1repgxiC#{>gVFRyaHjJ;JYaE<=XHf3#b^2Lddp6TVC8>4mz38>t_Y+ln z<{`krSDM)B`&(0glEr(zc*jnv(0mIfXmr0X-QGrEJ$aUj&MQuFlRmK586QQ7^bJ<- z-4g?jtNYvcpSoUo&ARogkx}Bx>#EWlTQIr@p~yH^RvYcCo7 z$|~#jzU^1#+fYqZsgC~!S*SvBvW~gHdT&aviY*?6L~}7ejfnwSDlp`5z4pp_piB*Q z97`z0ij!&*6J>6TfAQ{99Mc86@gu(AS{1vZ@>kw>vt^USKasJ6FohG68-%VtHN%za z!8>HJANlQ-5zWYTz*uw4P(ARgfG!Zw8VYm&fCm^t2m)FL1=4@GYLp)kPWRtD0J=_} zI8OftFaf}j;JC$u=qi=JPxVl7&bfGxllXl|s@oP4nqomuntq!+@$~NE?N16+AIr;q zOu0wGB23qJTq{_M{;U7)ko!ZL8Hgti)z*lkkUm*et>aq7j7P~$U@ z;r8O_AwB4AdF3r+BxaJvdxu|&P({tr&o;O~%EMvw42eA5sU|^7@m%EIKc5{k`F=*(=63 zN~Qg*P@Z;JC2n0U4IO~(MYfGaiZHfPQZslDS$0WD+b?DckT4`K`Byb z=zcGZjH6`!$+*i~?ohsx8<`J-kLWOQtoe>2f!lN7u=L$~onSyH`!C>g!+mVNrMf~_ z71(DQ@DT$7&*w%OKeo)-Mc}WS-juWA2=7whbOwK_hBi*OmJp%iipIi^LNKNb6NP=G z+*){tGeIvF_~<8C{a)UZ(dywOTSdyD{!2AD($NEqx=G?3@qcx_6ce>LQXa9_52C$C zf)2MC)IUhALc(CHD~ZD4h&G|g>H-Axsp>Qd_wuHAFNB&04GWbT;h*l$AWvnNtiC$} zymi;|d9!A|0eO}DDspB?$SnTuLI-3v-GjP&=6NUiLv_U*G1oDHa4d{&9S_)&0w#IT zam7N$nkhXt9RUWM0~74dzpjKypuuX`EFGLoD>tz|s+Gk$QT-_(5r?m+EGUCI(#e81 zr*2&fa_RT+uT75ENfz2E8KGIuR`u)fjJ!}sb4RjN$n0u~dZfA+BWS=3GK>*EMQquq}@3-O(r zk}5ymhcT-r64CjAG+y?hlfh7wwyYsefVZetp9((c;FH-gMkKzLU07UhVD@n#a4(wh zMk7CC(UfhSa}P4V8!S=l(vPeB+`&67+RX-~e9-rRexunyx1m!eoR;T+OP<|e*sXXW zP$9vrlcvigJY6exVnT3l>amRQ_@MA%$VBu;o$U~iYgSZUf&@k$^8NWolOVc*tLim4 zY&EIZ#`ho}Q3X5jLRS3aY}h+PAUTNtiDS>AfaUA0qc+p(P3PP;`<0g8hp0oU|KV*= zJQ6@22Iw3kUI7%16?B^%MWQgHX$&uh{x5)i3>ozPx8lhCZ$3H%kSmYqw(KZj{(K@z z(=z2in)BkWl5;vzN4RgELDe=0YifA1=@_R0JC8^P$&_5E$q-o!=={$Mp3o@O>Dc*;)px&Dea@o89^`Dp)W4)NdCjW?%X63c@RpL*o z_Mz9NSvTJ0WG(cc_1`y~gdkhweV;lK8?qNk`4-!U$-GqfkXhMlG5fhr_DU`?j3v!H z!!^h`Ki!Hmm7u8A1eY!*Oeib0RcH96@rKOi?62*x=Ws&I&^^aZ!l5q={_)p_&Ef+p zIbw&Ynk#37V|wLDrCfxDBcNBA8)t{e{JlhI{k=kBC93M6(ar7426R|- zne*Bg?9x6%?CWUj9SKW4#xDx;ZkqVBuo+5?Mi z6vm1mzVG>PsQZay<4A2kIvY|;xSgdAjgAt&=24`B+7ZUE3;woIF?jT4q8$Ob{ENYd z{1Hc($^t|HOM7KELnC@FP-{s^ypc4L4kjvi^MAM5;uN31jUgqcNr{c2$jIi2_v5Gb$+RRl*-ibV@XC0iay#* z(w9u(v-RH>kjjcB>x=FsufUNm$k=h?=^p>6QcCMnV7unv78V07Yiy@2-(v*#nE5)h zPO3xpysqAUO7pU5Ra;E?b)drs7xIvWROv_JDdlotONq;hxV>%cY$Lh};WkRvar{VB zzSH}84L;3S)m-bI=7Cq2D}Ry)eT0kUHl8^sbo{IE#*3V?Sjj;CDJzH%;AJ9AWeki0+WvdC5pXprW_`E|TV$jVF)% zUfVO3!0#_xgu@7y6hnRNIgXzGJvz^(bfWSVA|dL~dG~Pati|xk-q=Da=h<$TE`bh6 zs3UV9xz5A0%4|#Y9eUb8N{JzDQNbs1Kd+zD!dba8AJzDO>xcWidHL?KXTqe>L&R({ zSAjSlXeUas`!rI=gn5K@aH6B%65VD!r4tC$BS5KQQ}LK_M<%h9iVv;qIMru^Bxj#= z)}j1Q2kuw&f4XD2%njMGw4RXsh3CL|Kus};@0(E%y|dp1Z<9Gc>|w2W$pdA_4G3k7 zzi>$H0ka#RNt+iQyUfm@{=hD#Jr64(?XkKN@4BJjYa!fWH{=|tua1rz2DrRCi14uj z1~1(??n;!#q}+GWd(~GeqtZn!cF$+_ofz#4x#LLsCrouV;Xmxe_`o8!$ZY9mXR;8? z>iryQ2TD#8|J7$9Y42}3){Asr^7u{qmsTNY4_*ZhCOv87Sa`8^aCN#gFj~Xq%Lu)A zutgp9_aX%83B6z~$x>J__Gv|~hJA zM;KeRlOGaDhy6UjG+IIdFy`5b)x0f1ftLI4=*ySXRpzR3Ruy-DRRZfGX}g5Fcx45L z{GEwkLGo&Et_K9V0c`c!PA%X0i#zjzz%JF-s(@vtEgmd>;II2h=J$gA%n(J4$vjb2 zH{1%xLG%N!RD#xUH$`viY~KZYzVb#qoSP;9+#*_+?0*+^k%^1mbNrmgM954PBJ7Pn zX5bo(q?XS`R(HWRZhIJBk>x&nW}PV-iKQ`uHgoMxL@$IwsuR{>6Ctah_xt?fd~1M1zx!>p@^ttT zTqnK0qR94bz(-MxS^|zWJ%c=q)f*?G%;OaU8lR{YS$wU>I-(l1=+n+%am~?Y?KA8K zvPjjAiIWxn6BKa z(WtyhukNq_u9kMp@UiOm4OMj?>OUQPx%quA8d96nPA*Tl@KD;}GHiE_IcXP1b*8X! z;nt0HQ37=?jIL5C(cL;WhFh}r8WFpXqf)`Og~Lw;f?d5_KAoz7AN|a->=!KyRFam9 z46b8^$DF2&N^Sw`>zT^_fv0)-y*w4#)(mY`Wu6-f^#jh%u0I}^RVEaSgeYlk#8#`L zKzys+M|qRy1G_D$W!$-&Z?b`?!P57=spp(a&VmtV7VHr z{MY_ho`RJA)4ZTmIFU*K3FT%t{7!+`@;qvnZ8F9<-u#(Ck9f^(Amd<` zFVrt`tXyndyn$LgN=9HaTUt79@*%sdid>d9vCd_GZ5#+`!DTTEEy8Zy=Wd@o4?R1a zRTwkoda$V$&eLC@$Vc$`!SYRvyq5&onQF$A5{L3u`kOpfMy3Z)H4N^Qsaq zYw3<75UQ4JQg@!ptfwCTYk~>HP!j893Pg##e#pDy(h-4`m?4dh$PnngcOV4R-?00N zpm^FU_J*-GVMd~tIyS0X4+OIFen!prrD!gF(_a^ScF@|;g)BVW<$GtWzv6-QG#0`+ zObyqyG3v$o9gskw{-5->4n6I2mxQiIYQ3am&#;=#Bnlt0ELRyY`=R6YnLLJdS z=Kmw=t%KTV-#6Y0Eu~m-S|lwLw*ti>X-iw&-QBG~aY=#V?rz146?alJI7N!P1t|_8 zfsj4CzwbG7{@R(%&a;!5P4<57`*U5F4fJIkUhMtKMvIc?z>kcr0QzH5kcBda{`6Sr zWYsxuX>yoX;#hb?blVwHMz!OavsrMEzjQRIR3o#fJfns|%t@~PRB4sBE#aq~dcc;~ zApiDcT=V?FSQ`7mDH&#*lZdC-78UzW8KY;bCFa|$Bc`E*S*!tD&^kJ4l~t;YYu~bdMS}>$&GroVeLB?3=b_>s-84c*BU`_n(X{QSv&* z9QxG_`*%sSmkTP8mFD;6GODJ-IB@FZp?s z^+UaCPk$vRq`LSltmO65f2omOKTQWLa@ED_@ZW5gk_N)TrmOYD+h40o|Tfwnpk3Z`N2k~BM@j+`Y~luqTTZfXE@PBy-b!6ZR~ZYZk>>?mDvDY% zjx+_U_7T@STY9{-U8`MRGr?@H#u)54g@#4)G;Ze(YlmwJQ=cVHe(1{qWJI^t{!DC` z2Eu8-9=<@$9#B(uvp6|~82artnj3YqQuT&5g_0Hbx&Dp|;H8jfayvAgzE7KT%D6@9 z+4DQe2SOaYH1GqF)iOq$`CDXd%XTmzhEFEsnTY#^5nO?Zv$|kztrf#J%D|J6X-$E0 zx+w4OGfp@>X-$!s3`u~bH$LOd`X1+8Go9+*>rgOD{VP&+?u(_tbWJadSqiG@TjcgW z|H6dp*pSR(e31lJe`^rER@p4~d|z~n`mgRgW7#}rvjnGM<`dbR0II#F>>m~MLVYh! zn~j$v9Z99c8fT)Y*3G9TC5JZFBsU+Nh_j8YsU^E(c%FryZ51rp7-BYqOQrL^lEwa= zM`c7Ea**PRyRAJFbY+SYii*qd>BU!iU3%r1$%xH9KE^^fyUZ|`i%^?IvOnuM?jMhr zZ$MylI&go3qk05xd?-!jeb1+W6sIDaHD!t{+Gf-^lg=Gaf$IUMYe#bI$l#ekw?M z_Tjl>jho4>O??l&0THb4^T-ibl56_zQ}qk&3UHuhy6Wn{CT zj%?sEVK5N(EdY2azQDmMKuHyArj+{-KutXwH`Mk;j2}18c1+EJoo*8UsOWgVX4Wdu z`sc~C(FI(X)JK+p@v)o5sV^blBWtl&@`Jd$+ymD}ep=n4R<{3UFTGUDUxZg0hfwK$G7^0Y%`&sO zJ61&>?D_(w6S-vO2%_YSIx+- z?xuPdEf*6M3KD|kuq+p^M=C2uy=-aE%ihJ(Jl?kW)?qV8mhxBjI<^E{mVt+Lr~*D= zf4Gtn{W#uL;#F$20jab~p7z}1!jReXQH@*a)5W7<*RJM?hRL`Q<2G$ceG}O^Q9)C4 zS>^?fe|bc#Aq)`R$}hth9{+*&uk!0lpjLB4EAPNHL&S3m)NgrZ<)Jc;{Vo+0IDUh!?opZFJWgX zCQKg|ddYb^pBM(XnJq5FvZyUYd(kz!{bSM--rDhRy-ATUWM3TKVd16gcQ8M-U6lKW zvboMZC?WzoBcr+SUN5U-$F=k59yBA_&0rr_X`#08+xUmdQQDxLW@Sh`CsFM%s?Ad^ zt7-f((|6`!Yqjrxc3fZ%lBuAUpB0-5V`{es_q=W28&8%y2d(Ed?LXK(U2CfxRdsb= zY9L~~_?cm*@Qry)5S`*1HCp}6iAEJcTF(y_n(6vU^yh28z4)*44inSBGSd6! zb-qQkc*i%gJ7v+oi4u7VOh97H{ujSb`du6^4$Fo>9Vaw=?qX8wbBcuOGY?mV&&``A z^r=9~T>g|cMB*#|82G-%9KJtXx!lB*2uo}gObpJNRZW!r`?xyfCIFg#U^10Mc54jn zOB`CAfL>fih4PDxe`XhRqsusQ$hpP)YJp%AbPAi@0XaAAwSHZU5La1Ls&U-k+m97V zIq(~9(>(P!nIG(&M3;tJIC6GepT-={-Vul}%1GbLyx%N5n!YIe7n#V_To+$6dyrD) zA=<3}cjXI1PZfLROK7T*LlWaJ#l|~`qmC8AfmIu(JXdr4twLoNl8}aEBVekcMWC9j z(~eVVP>^^@Na`!44JHER+t2@O9dk~3Oev|FU;O)fQte7htE%=El(ScLnvZJY&vshR zb$^FugdejDwfz&7_p90Tw(<2Aq}1Q1$b!#S`gtZ}jsxOT*Nm zG~Q_A+jjMKXFASJE3SL|a0+njrcHp5nRx&(o ze({no-KEtb&e2$4Q6%AO6g?Y5=NJ4< zEqml2PM8;WRH0&$MP!GC_@_l5Ry*1i_~jZ)V>;l`R&#H(c&6M1jGDHoL90x3SRj>MI*yI9}bHHrACitUT2nDdZIjg=H&&nhoRePNW? zq__VsH}!Mpo?g9o)&dC@;$g95X2p%Ob75r8@gE!6P>)ww+-EkSs{L(>+`@+Bnp462oXu$c?;KdW=NFFFJl$k-^%#;wdzvZj-)QmqK-#Klluv5;vh zM)@wC9#0y_PAtz}GLh75)dAm+hXh8R8wwGs0wU376hm9A!x zhu^`X6SrAS^CzRKjFnN5F$;JNMT@`7`>I;H4-&tdt!``KlSonjJL^i&&9Bw8gZE-c z0P`<2t%~j#h@vfp6sC z2+C`ob?cAGr1eq@BF)x?7WL*^ZX-5dofM3JkfxZQWrjWnF`=Z_aQm1oXY!WKol5GOY zVzji(4q<;F6;-ieSCP|9aG`u4JSz)IQH;9ywa2#&#VywV_s~)$>n!=B9%c}%uO zHy~h{!m^lh<^M%&5O}wF)veJ3b@>h&2g+=BfE3aYV+p`%v+9|Jdp4CkLc2(98|cd0 ziN7bjbsw;(^n;5!Hd;)zNTH1$#DbF>4H=V-iXFBTsIOZBE;ZAM3)E0@cPTl7?feYO zi&p@6`}daA!l&(QcqM;6xMim(C2~WzFTTVAht6rz!*L@&$~4gB4M_c$Mn(QU%u=XP zWxlMy@SgG0T@=p^Ym519?q*VH4Qw%7lnonMALXjpIdQ7G(hGEjj2fIHLI5-DF)xqS zlSZX*F32`KmqIcNMREsxHX`o2muYit|E+bc5G{Un>^ z5_ee5zNA^)t@*zqf*A|L=rlQ;uBZR?KXF~_Fyj2b)Bnpz0!}x9(b<4wzn;@;#xdPS zV3%yo$=`S}dhve)HsJUh0QV5a9C&EiSO4r1+)cFly}Gh~de=%k{;y2AOIW%)+^$~l zn*R@Kx>K8hK!6-oiBw^>bC=E^-Qzmk0??x4W|Ig88D|e=e<-#rihR0Q>CDkQaqln9 z-|RsrhdQoU$vNH_YoV+Wzucc#c2{p7H`?3Zyf|yT#gCW5Ukb)Vclr%6ZQKv~D&?xy z-Zyu^_Ju`k3G^n&p)d3-N#t+&j*tR)=`XW%`d57jZcb5^1)P$x%MMpZoTXp>@$_&+ zn`8?3m@`&IjJepC??gDGF}}GJg%_kfT6u0>{0UMec;fhHx?H+kaJ+Dogg-Bqy5I?k zU6P0cb9BaWFXftVU}}<_#nlUseob;RF4eD`{aNMN5#QVjZQ*n4s3@g)yC@aE#rFA< zEg8(yYR?6``l+qY9dlQ|yH+kotEBC&LDzLgum^WLK#zgf1|vPx4^iCy`owS>o!o;Lh_w8e;F$ z;Tff4%w1=?4kJlVi}H>yVNX4z07!k(t2@yCyEW5hEaRaZ@*WfUxHf2LeKNpE2V12#U6nDk5DH%tFtG$4TQyl<^KfA9uDDZ z2H_coqhj?mAbp4&!7Lo#eiJezm^Jj1ls|#inlDCu90Y0Cba-pkew* z7fiX*OYqEK0GpJw{ks!TO+tI&61#KVs`5*;+-B3iWz!dN?i#71=hjiHV?dn#w{y&~ zL_?tu1yJ|?n||DI*Uw^hJ-SmK63b<58KSm+?``9>j|33={MxI|I0<>OpZnqaKMla= zprl>)c{at*gkM^fIRb*jnfq!8W_gOuC7*Vq?Qq264|TAPw%^BjtDJST$9WfW=+Sdt zgkCJ6k+)q%-%D%3ocR}iU$26f#~~jVdWms#MGw4QR3Id!C6pOL<>g{Eq8S^QJZeI8 zQqG*dv4=hO6OVY^80bbzpf&8(u>sAlF4%2R*?zQNDdc|Os>At*lHO5!*40s6T&BJ4 zLICgk&^DjohRr4)vBi(hgXdU-QSHX@M>`uk^Pe+PH-Ff@7~c92Tayy8v&fs;Ewr+z zO?~+N;nkF(Cih@)(2?m?e253#5?PY-BSZ4MgEMU!y0=5k{@|@;DY+sEfXw>)R0wCW z!2OqYS$v(6K>;0Iikr797J9}dksr=q+-L7p_C0o9&u}@OB32YI+(Hf%+?iTvJ4TKl z1~?X&(O8$L=jXV zrJa3Ouqtn+-mX6RB#iUbxONvbKrQ4#u6`>O{2BC-QudqAPS`2=xb`*2I(N`H;NYA8=dN&gdnDUA=Njqiz0l=Hl*6`y1wSIFCo0#ITFY)(U=x)$w*6XAW@a z_n2vx6v2YrfyCwDP8FJ zwJpe{P6nurg{0^FZahpZBi7byzTD4^$Qkes@LoV8y?hv2gOng}q`%H0g5{vjfcrgk zP9i63l!f&PmN1>1ddj%i%~NokJ)}`S~oAFlN; zs7?yN50rLp{^{xSujfi>M!lm^>SpG`!Se4>+WDPL-$JqfdBNN-yZ3t+h0%+FT`zct zDpX%XKHQ7?+Y5bHVyuD!t!JZQ7Xwf4bqPP?3+0WC`tvC!A5{`A?(l)z8f_G@;PSDU zv6Ywoo~l#tQ@i+HNL&LR%YxtOkCRo^ATc}h5tP)gx|An^(!RS5t-^fH#}%i108b$B zE^EQ@PGSIr=RfWNo8OH)0gcuDmUFIX?PNA(t=ORen1H7(q z=tf`gr}w(LWT>sl3c0e+*%0+SULXkV+B3tRKct-cOcNt{2jJ|SZ@7MU61Pnb2_Nw5 z>IsD6jB0+oUxJ1bV?2Mh%H0eQzjxz4Owa8j;+5Qnp5@|KNBB8pNk)Z`UX2ja=C&*j z(kw&U#EoT}gJ2K56epFk$5v&%1)yW1;?+tiY0 zkmvsYaxb`NgteCko$lF}+88*hUZ+ojnMuY7xA6|8%M&^nSW5e$CZ(N9pgWLZTwf+B{q&ozv zZYoy@i(tu93)5O2S#WwY_IjyvnF8>QsJtiEZM)~%@w2_Bly?p0ym;L`11EbN^^@N3ePlF=hYL3G%InEa3{x>lfh8PDQ8!Zd1Zdt@yG^dp_4ZA9#E0bmLS5 zMV|;G=i8fh=8#P+6*)1k404z!28$;hKJkm`9d*QbCn@%#jaq?Y<0iPIl?tuJ;%B-$ zb&J>eC&W}btara&{^6(V?CI5`)raQdW65x*-k60$3*IDAh4#0@qKkTun**{*%$kIc zQ@A3&RT%Q+xP>M|Tw}T@;8!!gu{IFvSyJx)L)sgcOz%ur@C+|iJ9A60yIE0T;}lqP zJ+*aL`@=}<0wD@S7M7Vx_|uCY;dOJ@hM)A)KXox?jV%NqlSkan(4ZLNX8 zJw4R1erV8gQr%JAdRG%+X27GbtL}!J^M{<2FW@7c8W;{rKhCc@2L4?!LAR#W1D+27 z;j`k8G@?ATZgJ#`B2Ee0lqswJ=APzKBlgvxWj{0Q>A6{M`Y?wUr$dzp@E4rx^5+z1 zt27jaOZr~uB-h!Elu?TAs0-pfLVp61%=+M1XD6Sd^rlE6ql$bN2Vgm7+K;n=i^i@l zWHf4Od$VDC1X~UF|DG6Oa~#4&U^j$1R;y=&Ggc@b6MWimXchw6ptqS;w3tqddUtYc z;nM)R@zcd{Jbm$k|IeR&gTyXc;ojL>6jf$vWdptFh0TM%bBi@a<8Cy70pjOk+me;Q za6a9bSs|Vnde>U)D}zv3XnyN8Atu+X%6aRB2#5I;+uvr~=ar_#E?Gitcd6t8BPsw8LIVeMq1Spbud8^ zj{VDU7n*<%KmIGT^NEqY4_2fr$&%c1KqVVX{na*CcJ#GZOf;tV`8QhZhKWZ{6K+QI%P3 zQaI828Jn9rCsEY)&u;_&oR2a^KarV}IpK%K;5;)EIw~Hyn6kFtKi~a$)`Z2Gn|N6~ zg1u=DV$8rF7POGdV4InXu0NVGu#_AdjU5i^yLim;0QSl)6tdHbxd#}KPnym1`KBm6 z<<7lwZ6qtj(L^R^Xu=s7KZ@g#lSKw&6No7a6c9VQQsQ2%EkC0Q<_PVa`#l3$KL7i1 z@(5Dc#D6Q^9EzVi++hPfz6&SK25j)7;kB~=l+nd^QVOEaZ$!LSa>-$7W%Tc&``+aq zn&as&M1?a1ee`OlJo>{eafFl*r+1;UR8d)TrV3}oQcYpr>9}Fd&N$m1gkqqqI1-X2 z+dx*uue~7=Mv%RqJrFo4c{NeLaq_YMb0p(0W(*kZ zR!$z(RKtV~YALSKr9I{;{{F$V!Fz#a+9}lGn71{%O+bPF1TuGCkBrk_Hys~&-zS$Y zdTUNEvC6jr(jfaql#X#7@UdtSUCrluU$`M+MzKT)2Y|= z?Cku#>WA|4z1WaBRiU0g=WQQKM4*(Ul{-%Ys#(xNL!^@1R&p3(NAq@vo7v|8b&@hV z_iWG�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

sV<;Q)P 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%0ANC$F(o4m_@z^kb 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 &6D_Cc-yyU!xqjle3_dtZFhj;R`F#-c#v_edx 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%0A}^ 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�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

    c`T5%Y-L{5yaptvvEZouph9>; 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

    rsQLu_p(!gd2mWy%nsK_UXW5> zU}w6WEr>`a^6muW0LSWFh8^?5)Bz5xMCF~)t<_NX%eWHfK-)GyjckGvh>?2suEnFV zBCDx*do0w@wx{+9wBN^seGDjq(gUhWUhlC+$Km?pFS{vboha4#C@mFIwElBTMpm18*t* z?<5k8E8+zwBG~C*j(-Jz*F}X%fKbbg@VZ9q|0sS(T>$SD4H)BDAf@flcZ3aZDib@d z%o#gq^rr*3ITvvO8?FDS!>0cM8Ycx9V1jkxm-w!M#><29ys}=*z?wuHrJpRp$AN$| z(HRPbXDuaSI>GopEG~)t6{F$F(@Dww*N_}3C(1gbJG-Rj3FVX%N*RNy916Ub60@tN zNfJMr?(51hKXiO{pN3OMbG&2|8oja4c)^f+?N|bBkvSZzxz%N- z*nRcRGl1OXpq&2Awuj?$@=w{`txJ=?ruudrk~TzdB350gcbEr_B4VadFUR}uhzEE* z=5Fy(YB5M5+@X2<;EI1eKQF#RIdSk!uIq2hyR`djl~UvO zPjemlP-KQL?~+R#=zVoh!)M{8IA@UaQVAkSLG5lOP_AWMs(;kZs5-Ur$WMsBC(ve{ z@Y739rE*w#pyJgp`r_r<^~!no%Vdewkj2&07}n&P)lz+3z<9Ud86^D>`a`ac1NPEB zAhHirnMmq|kb86FV-W2tj8U%Lb4@7XxdXVUl#+?YAd*?9ULxRxt>H|2%#(|X`f8v$ zO!EPXkyB^`+FCO(`k=3nr$scNAU6Jx4ahZMLx5|6kX>>ykFF=y!N68u*vft#MDc1R zk5k(`;Z6T{8~YBzJX)aMvvJY5tHw_7J4)??g6bPdY+Mkz39)I2rejI%6z8So*_m9F zm$pUO#%28*3cuW<&*#{#=W{b1GuYHXVj4@-aBF5uP)E)h_P1?YiPAXOjtg)1-WA(^d^ zr{jP#0(4l304Y`83iY|>FIWEZyhO8O3t&rK;BnrhZr$LalEW+9f^`FT$4G=fUBHWF zb7{@kT9mmM1MNSrbY;Mfu3OpExWBRd^QCz}v1arMYJhKn8%k_nv=vbxpCH<@RT!C_ zbib={5&_ym%cA9omM8ImKX3J8%c`kVBascBQiuoV8YXXZ5L6y-`-rO(w}=`UxJt>5-=SW-yu2A-JMd z<|KCXYhCIYg1*z9FI4<-tMY2d)JVMh@%@KQ+IRg$sq$MMC$D$|n9uMCqx(T?i9+X7 z7sKyLG6>wJJR6B%yRx80yiJuJu+&jrg0S7pZ_3D5(H*%RUJR2$9~U_x3`7Nokj=C_ z$n*7-8!nspp-hTL?-Jfo5I>ntpVWLSG%AMUoFm4un>4*iVtCC_64&>Z0$iH~!Kn2z z%+i=up}PHoPiS!)cj!WPdmDSGV2yB+=u|a#-pSi^Y@X|5=m|7s?ot6(-FCD*M7#9= z(R7w^QFh*0QW zpa1J~=9-s#owfJ=E|(K4_aHzVvX4Z#K0Gcruss})Kvj8Zp|v6S3qvMta1LpY%O!_u? zP*T#IfX{cnw@-$Cj~RSNGvyKtylO{8P_w99$lvHHNTby1NQ-6yXEnQIXF9S$@6V&l zzE0#_d^mcYzVEm5w!p?%#9X%;Q2rg@iN+EY5X*At^_WNYTDupR%-kz$oIsT2KYdf_ zuVq5v)st%RITqNuu(o~-CjYpd(@TfJ18Wp_L{?INw|ZGcy%qP*FQWSNTZrtkfv47I zzS?(_g!z;MUlx_UP#P?!3J%+8QWPp!a?f~_ywINd6<(!Vjx{;6td3z0KaHpVs!_DR z%rwnc^^}l~_~O^CgqAlyLO1~(ML2LWg;k{L)>Iy9GngBBwdeMD3A}s;v4Kcmq{Qc2zpvH+U&m*<+%p9BmGolC@SE4z*c*8pQq@)uIP9h%^wN(FeU~=515U zcKY#Xk<@K}0I{BDX8Y6_N!QIou3ED_I%a*hE&Y|w4J3EcYxvVxhk723ed^h%VZZf~ z0gCmlkbiiS)Vy?pq3KOusSwO{S>050v+lPh5Q;A|ETir=ba)bq!~@SG)}R= z>Qb5HGGv^nQbC^b7m8kv_DpB5_#Fe1n^9TjEsI&$Y`b(ooahnjQhK~y)~K%4Hm)8x zs!mhWX1}NAlac2>wD}#9Gz9Nx7r9oJ8%8-J zw9X5yJ_Wff?sy#H?0@|0JM0zyxhI~SOP5UwTAFJuG8Ny!6Z&j?!f+|Edy>7d6r zcs5M(y|_s$Pm}|aV-HKOr$VE!21agG#?k%1G7SK)@&xYUE@PN%bk#~P=}Be?*CPe0 zS;{25({?=(1f#KMP(tBO;M|LqnU*S6DaeO)12p2-=lrZK1)rTl%OeADf8K(3G%|`cKZw^>Ura6yRhTDNG=Ak7OQ_6M&Q(M} zHC@W$K;j4;0}fB2OxYtDYk$eBN6u~>AcP=TO_zyuVNjwJDtHw*9@LxlO(PWSa7Zrx z0#KME?MGWTOTr2Fr1T4y(U*|2H5qL}6D?Nt$=qn;lE&ZPZ(qMU{L!_PTz>B?% zEQngh(0FVbLa*UL^}?4@{0x+=tzf4q!fMqL5VO=L>t_a$soPc$R5~5G`R0iZ1MYq&fIY zDzljxroCq!w1~V-5~c8E%f+%uRMQPy=2;rG_bfzqtY zQ)8sSL+OR?o{&|5q`%2dW5Gn$&@EMtzu=vnXueC<`2F9uC8SQkNb|o!?RIpOpy+7{ z*!4DRPq1-~;APa)_4fCn6#YxX2Hm+5sHsbTw+Uyup}4qd>SB1#y-9FxcTFJQ#hl}CzJSu=8tqC_^ypqqAkfG9Pu@L-lctJavuNh#X4vcr2iRSzp>mzuI!`$x?}q zfN7RwwY16FiO@#4D~hhf(aO{f5)a@={(=7NnWWT=2Nc*fxbZt&$wIlNCbsPDCFog> zdfc@(Rm9UCC!Jg$H0~9UtShScrs6rVJoMINKr@l%shI0--n<7ci#9&2ZT@s_^bn)eudTGFMGMQW+nYyG53dJkh4BKU^S{_0uQjN zd&D8d0yw)-ko`x91EwL?w7VDh;Y@pi&u5Q)Yv zpZDvh{NZaJ3+=%Yonj3G?aymXRdF#AG(i)8zaPCFzLCSGCjES! z&7eo)<%nEM(DMy_!~d&waLRI6Z$L4u{_51xJuZD}B>HEM|Gwl9KL0O^rr^+s(f5On zYlEH>HC z66zOCk8|P=7KYQKV`zRg<5?ML4Y~Q}jfU~-Y`F*#ESy|t zgMbCU7tSpRnwl$_OCz`&^PdW|j<3sW5sk@&C>O?49Nv0bxQP0TteS{MFH zd%K_~b#bqq9uEdu)``Q~!B5FAKW573`mJgj7g;1Gei_OReOXxlFGO}HCBZ^w&%%D3 zO+xWU94x}^pSg>@cz|dU38H7;$X-H*mEzqRa~!V5J_umRdr zao9bm?MD#kDbhxsY0&QpBnV)qMN8*A15C5hv)ubYH|hMVZ`9}dK=JWzwGw3)vv4ba znOJZI@4Hue$$uKF?sL;VMnA(KT+c(J%+9=mEHlJVAGqtsw>%p4rvb5GaZD7(!lQ-p zdE|W5`$Rh6A9_HYI9{)q$zU+&S@l(#n=TAY?O}@bG4^eg)@IJxL~~A@$7^I+a4nZc zBv@U5x*sf#{uml$5(CgV*wk+3DIr|E0+1JPj{J@!;{k#E@IAF&;B9I41@N1s-a|M* zblLvKDO4Pm_hZL%TtW-!0e8$NH#xNCAQ~bgUT27-p@4?cqH zawBi9jz-p4{*r5p4iZWpF%9a88WhS z_zZq^ZG?u_KG$(G!jRC;wS%`=ZIrVoRiO=X-FNVJt&Xkbd>9i|XlqD29g!QDXbj$M z3L()}jzXF#_>O6~7=QkyL4!Ty z!6X1)Wuy0b;Na9;i#w&3B3GquN}#T>`-Y~)Du4^mi{@5ed`?)%7-%N&O=@230Hel+ zO~Q9XaYux>SHwM|J3GCem;GW~L_+y>Z7&ebZf-su+_F$OC9TKur}r0(`ocjsgQhKQ zZ%`}1-ZERl;(-(CW-I zRAC)YUq0IHgXM6V80u5(*FC;T*DlBk#H@fzXae;L;f5u+(B$b99E^4mb|Vp*`jXch zHTiaPWFg&o?FrK3`Gi)rKU9T|DE3r(wrUh&@u%K=5pi_uj_v(LLrV<4#hxm< z-yfVJd@9Ucn~+Ic4BsB9%=<}55R)i0ArvOWf(Cq@!HoZahA8_6)G35wdvwmq&p|kaG1Z$F6z7Ae&(=x_7 zZ^IoU+Y^3KWeDKt)eL;kAKe~QVSNlPw+-2nX-xK9t6w#dBY3WT9K*GhyZ5=-;~sqG&0 zDLv)D5y8quiE8hP07QEKCq7O|0NtwN-JbiaUrMJgygu@oG%bz7;Nye;9q0W2K>%>t zCa}Z3seA1}knpdJVE?J}?%4imYaXIx!Aj3y`Hc4J5uk)9YeWMY(TK<#7jyfthj$Q$MGE3^Hx7bLwy>qt(BUDDXZ zPV}!mlp!Vdr9V?6lTG;~zpamJ_6l1tp4X&~f}+g6Dd=#Q6dUUK*mmB^S3ekd@N(AX z<%#d7Mj5LneMk1XhWJ}znNuopioGEi8n>0HZ|imXDJhumbYxV-`+9KXu3JWx^gVC3 z=;gvOq^=~|mzpk;vhHIx2Ix3;L*>gH&gD7` zQQNIEzxuy=VwSj#x-!%G{JKMLr&F%-qVKeBpw{C-Y4A(j@!=0Wr6m_;G9+ygI5{Lk z59g(sT#FOU$5j40lS6QFEYhC?*(8Rkl@>Rv#}P*`cFB(NRB+R6Y0(O$P&_G!KX!UU zGlwcvj~7P${Ub3S5@BycjrRmkqVGvm$=PgY@~cn%y{lj$6RE%uOf zYnn3QH_LC9RyNj_%pdqopR1nW(?X?##x8N8nsfJS9-X1j=|<7OH^ze0 z>|)#Or=Ja##IsAVKI;cwSnS_TSZhJc;GhFb&Q`++pm@VGeijDVkrkd7I{Me#uzvlT zfC*Q6%k6X@-NbkLnhT*c05K#48amy2K|B5-u?@oti?@sIO@;@SpUx7rKvxU(>|`)- zab=IQp|(H(`z0CW!0)*6QvZl=l_gcLQM%1sdtqj?o1M5Hr97qTM+7tfsy&@02aG`3 z3!{q#w2!~-m3y~%XMHzm;q?v7@gC*T3HpiWe4&NB5h}yukI!R8$(zg_Db{8VIeY^< z7-+--)nCAv2js7)&4_6_a8ax^yMCMCJq$;f#XZ_HN^uGxa&;Jji$c$>9$lUw0`_-> zfCc?mW$?TUsp)#jW#?X#n5_7H8bIq#Bt8aP0z3l)<;XnwgESP@B%FlLf&Ivt;*r)i zI8KW3CfIlyKJ)fQUjHklQ;Rgh2f@-}o$H!Gj#}kn5P=7>!)z)c+#iIn2t~>Qi!i#H zTED7+bLgMz&7nUapzO-j&f9fMb9Wb&WG3AeqRs_B^Yw6PXvg6MdEnm~S9B%1+L?{o z$eLG%Wa4*CSMa3D#GXXOvdS&lQ{(<>SXlkM#ZI| zUY{+{5&rJ5q+m|WkGnyu+^fmxQ0W|Q^j;tT9cyDXRz-Q0rl~+az`mi=T~c!RkhKxo z`+mVi@gD-pb-D?rKZW5*QT;Nt7F@mA_SFXG;F^FM0}|38V1#6VV{0E2?Syt9gBRk; z)>?Fdzqi7(OE4ckr}R)6Qy82;mgVx<*ReI5cH4E1dfa9J0$jdALO~BQ!Izt~o8h&G z;;W&!#2{cZ4Y4<5lf9XS9rxD9Le z`(|>sYW}+c1Y~qNy}0&a%#?g1K1gsFkN>kVJE_acm%*Nb7$E3Zs`#g^(oFPRtrgEH zW|WP(Y_oEIz)ZNmg@OQHPOD7A`wW6gD>8ri0{z^^TOzn&r#|0?FB0nggskj&UuXsQ zzp+?m*xwQVhu|R12UZtu_Ze?ev&G*r6OY)(^)8E9|7?e5xRc)jLpl}H#ml=PBxH}@ zm*yN8$F~u;!CtDO`8j^K;!RFq5n9kwBhm-5IxoNH9x6pbxC3vRRwJ+mXM0~+AflP_ zw>C4k(_(=qaO(96?8$9l2|Fv8cu;XdPI4?^K`keVe5L7sv%hm=PdU@NvVS2BfjWQI<1#0EV>P1p^)HCp|AvtA-mL zda!U7k;npTa1FVE9UlWzRyyS*K45?%xB-RUN}%TdL?!A`KgR-VNOzF_W%F&Jp;b@kDUwg&LgphXm3=9jbs-s_&5-i3g|wNt6%r6wyc|iOQoyxj@h! zl4)hq5!OxwA7d-aFk> zSz76?|J{V3BO$JB1ox~i7`z>(M%rLb`~|;GFV@T5a6lSmaQOfK@)pqT26Md;g}ntH zDrn>la$KvYb;-x0p}J1HoYd`_*@!WLf40YGe{%%yYyz_-)Ke>;dH4DE@#|4IC$3ak zY0#Lrah7_vB(xsX7vGLOc#=qW>`Urs^dGl<~ zmI67=k;e?Dkul`N^?d0^)egbAD=0qD+Zt6|f{r2+via!0=4yNXj&Vc_jk(&OaP207 zmn^?H*naoP+6k*oV{wulYGgq_vv;1&^kj-<=Eu1=4R)mw*pvpxq?Ep#99uuc@6D;w zgidf!usQ#|xqr_%i~r4zg1}Qjg0gsyiZwcG;e-0C!~S11h%>^EB$3q&pNkQQ@;Cw|H#EJxbKdNHuV45ATxFG= z97Pr~Gwn?D?`rVZze&_1D;iy}g&TFWApdmAXAmr^(41HTkoi8L&279gGgMDOq{MCq4q_B$YiR9Jc;dkwDB$7fFnNV z`^ikKLh(SXq{v_g&wc2oe`Rfm}~PT;Qw zx6tv(ry=ABg3SG#co)b631Ky?7SO#Nt6$ z3X>}0^KiZoUgP2}_2Ck!$IGaOb?_bmV**1m6_qa!Vu49)+52zRR{*tlv}1}G5EC^F z4}XEuFg=z-`Uri^p6wWxA_;ndT=?USj{0%%sp-ouN!3eWp9!PwIR@D-Fk3+QN3C=m z?y_Tf?ZO_ik;moEXow4R?8#f?uCPYTe9N9aexLeDFu_}mi7bVbja5X*MR77bg(9@t zeBQ;jm?cAoBttZ~VTmrTk6DYuMLox&38_X@YF-R;| zCZ>kGziCy8muK+S7T;QxNDRQ|Za!kcr=w8pYAC1wTpd`~-N5LS04{eH+OfiJRqx2K zBM&}byg$)7JMuj*56DpehMLRnU$zlw84iawu-)HyYTmWLZaHGEF76DJ_PJWPr4}L)?NTCStvn52|I6q@^9!%C z3y;8U7%$Dg?mY0N#F``+6BGbfQUW|J3`mwp<3;2_pj^ZX?^@4lnMv=HDf$EgF*|S= zW8i>9|FSXZ1}pd4vZxB<>VPX!Y4^|u4u$7k9c41m{>%>)2;=7!xcT}sFUIAg4;*X1 zS_qp_04u@FW&i;#!&=L={!mY5e};tgq5C9#44PA%@Z3qCmclB)>PAoU&izqJRdFH{84GXc&4iuD@_m zyY8@$C=As9N@M(jpM=p((;4|&`nO~hGPzN~IlKNMh|2F&wA1C}*^`Dp)-n0)jU!m! z=BX>|%f*8JTgJ|Ma(d(uR zRd<2fiTL0Qs0tx&#O}FBhJN|;;M;EEe(rGWF&vs?&4EN+N}!ezYhUa*G$!U@zdFf> zQ1v&2lhpdO?cO7iM~K2I)d@2aO|prL%zN0(dX3blqA$)Xu$TPf@B^5AT=;O5$rLJ# zIW*qf%WfaG1JDU@e5@U#a*;2(KyPH@PZ$#N2-(01Ah| zzyrWVH!uckgSN22cj}jWmj|%&*n?3hH;$taYG4s=()14w8F&;9Pzhu;3YE7~s0-Qq zR~=*2__li6sz(wPfbaeIEwC{H65OT%A8?^Qb%B-_>h!=&068~+9_OZF12Sxy@F+ZL zVBiTLj{-QK9|MWBXiyQOnUolkkGNi*x694cHdLuBcu3~vILmy~{-?gax!RE1v(aRi zH!hnn($?JZGS1v-vzHNCRKLJn-S@W=E%HM>fxPI$qky%l9>8h>i~y2V}}yFvq3 z+h`+9KN*@iwVv{BkyL^F)Z6EGl;}4-&#oJ~2^cL0ulZwguewB7S|BZ7$b@4>i5i;Fd^N{l98Tk2jM5R}GohQnpD((H2$COY0mYHlu z16E*884f@DC#AQf>60_9ar~}DOz#HI4>2SfQ?Fl&5?5N^9`ZB}2VDhOIC>ytCQ~k- zc7(gXvdBCZJ52syeXQQKE~09H`S$)5+Yz+P6ts_~KGk*XvpZ0Hr9hk0{$3}K=VSWP z4(7GLmfLh+L~$|apaUCAd90f;}qC>-ub9Ue`$OJg3fJI#5H9^YOp=T%_$i<%BOsvIfoAP@g1E}^?ymFvVy zK9i3x&L@NqM6=}maL7XP0^}v@!)ZoQzCf5-cIt$$6eFtIbJVH<-_AtB;H*1iCbko} zdk!tr7aq0?+v(#poqS~*}0 z%*Z_3Jf~KKVg+rT*%x5hc)Mt3KyU-nqp^EY+L3gRP(dt=&kemg(;$^a++2rNtb0OLDr-$Gf)-2 zu6rRcmN7!J*+0^m;CA3(M<=lk+E;ykcfj;h&`Bnmgl#@n09DeIF!i~Fvwrg0|5oCFWZ#aWUo6rl}`mF(9%gc3(}6e$~$e$&7*pA2#- z8X+ZTmR>33L1=LcY>jK*G`vh(2p<6j?F$3m2xIAUW8uxfZ=@m2#78gdi-H0uIBQnqjg?Es{a0L@x=)`Ce_g3H6ph2qs5Gtq0r z;;jkvUP)>>%C-hJ3^%be6Y1ik`rUrpBlu)M-KBD5=RAieml>mvv$iPUNIM& z2JY1d?0cJVR?MC661{mgE8S(3f+N2E_^OSBl4|z!|D*tzP2TnR8Qd`#FgaSb{u`z6 zhJ!9-J3uihA1kSL82YhS4Fr7lV|*B2?I0#zWNvM$mKrhaX;P)VX1DN^+c)gp zt>&lw|2cw!eT=1eTkxmhLun+n>`S! z3r;f<$Ka`p7kpK|`7j|zqV+c#*MSs}6$#-75^xKJw1n4w(3i_eB zzhlQm`wk->1d)$vM=nM#PQ5r0y{98D zVuhzMaPZ<;B9FwULrk^UIi1+HO9?~KGUvQMXn3+-pe>rd ztF}|$P%t8ULqHW0ha+XkA!2p%;**Kl`Vp4|m-Pz5{Q`(m6nMrD>12zQQfT9rK%drj zbNvu|EiAdGKS(LY4=9PCpMH5a-oPOf$^&I=%;b$_A1$2W<>>>s1ik{vC}#4<>brV^ z82G<;J(w8@Z7W60(60DW2=5w`fga{s4|lNs_vDAdK;B632pk+_7h?=Y1uV!!hh{9I~~wt2Yq78y&mk zQp~%5PzZZPepeP>?zE9keEwtYrS-9=tiGll`mZC+Oh%-G#tO&16;D>~Gt;_?|6eEgZEXM0O^i9C7CHLzncuQtpi1bf zn;fbyo}G-xGab)OPHgeK*H!)8mPNc5(7qFvdH;_&m`D9%KoL!d&SG{jsa{h;&W!K$ ze!=vCJMAOgkeY|1dM3;=Oy#DJKln)@&fV}eC%E?W;DR~hU^$nvaT#(VNFF{@#iMBn8jR67qC-} zyuEAXSGC!%ej`qi)0pIgVSz*=_-uZ=ztu0pPi&^ZiR#BT8<~KEogf^vy!xi61W_#_ znLrta@e?A7q?Ob8l97Du*nP`|&F2hpQ!9yHFtAC^OXS>#`;3Hp`c-oL0! zoc?i^XN3V+W&2Q|1dXYON7ntfZxBlDYrBeqps=bVSHrJBe9%^`ZZu#Bq^$N$6wi5> z_bWv&u);wz`_Phc z@qXs~Y)|{@3?DZnBl|&e{15I(kUTOWI79}Rux3Rp^g0XypM=-qhfN)y7I^y;0pgs8 zAA94T{)I<>u2NCQ&4R>aSfG#w}tVu^NYktd%clQA^;LZ9lg`{KUs&b>q`K z^8UqTe=Z>NLS~cJ@UJ0LHY>Mx0sP+`4vQe_efw>a?$93rwOyZxyrIcky_Mcbq#V>s01s z@N-LN)VP~@040*I%{(4jy7b&v)g;KDH{qNJZRlBJ7MsC97M1Tb`?f~gy_JdQUd%*w zUQU6}${~Ee2n*5IKG6e+%Z6skFUn6rLcAt1d1f0yN>U&GMtwKvH7tYheW6g%pPqf6 z$bjo~J!{$QT@&J>V|IX62$*MCVl<;o1{PG!o4O~B*Ir^v73Dn;jf+CUuSPdwgOexyJ|Yf-=$`j3mB*?|uGER9h7If&WQ!Aqet1 zz5r)SoCu`hSx=VBdX529w0qK zbg3J0Re!#>Yt3Gv%TkSnfs2$?Xnx#A37tBHVT*plFy8=2aB|l$xW8K{B9Yem`}dQy ztu+xBuo#L)bPLd*18O?r5sRcg9d42Rbzjzx7xD_ZDxbXfWN? z9G*Pa%=7hrzdGN7)LC&pb{}-LCrulno^456%{C)AWNumOa7KwVGLB^8TW}XxFA#r| ztPe>7t*7Um7^7@;>8B zIif3|WOT7*kiWoEQY;LzU)T?Jr~D@>NpZ;~@&+dXzzb2^30*f9AmQeWtL+ddZNYFu zMmk5R&!di+Nxk0aXEsi#V!os)b>Z1`U+Q}%yK89tO#h;W6sVt6{XI`kO~#uEyw`YF zxRamQA*5P&hPGMosrIG%1)xtmI409B+M}bK`Hb*;4koqRr_WRt)TJ30z1}jm?`1#x z&A+pCc$i)VW_U=wF2JmOvgr((`C`g>Hg1bI!@sIT3A(}&2?C=cF%7!i@qoM60Pug6 zpO~O>S#Seb=AQ#*d=#9akE5Fl7GogbV6{Qa?eQA;S0fDk-y1yOpo19!6v2+88jWqH zgh=yfPUDbs0ms{n|EUBYhJSECcmv20T{c`-y#xX4VrlpMxtu6YwE!g6Lb=otqRiU| z2^QT1m+U`gNpZj7Wwi{R;a2!nHd1$3-a1lM3BBzyR+JP)@;NcKt);*6qb$SNatupEEQ`?^YhGF+FALdV3x={0U!~^YF{P zXLhPbpXjKUR<)Ub&I+e{e2d*-*==QDbFARAEB#s0!|It4`F{k$z4iaf8Zuf70Lu%EBq4ylS>PzbDOO`!C$>m=m z>1UlAsq_bJY6(ed)8hAtj8O^6^}AW)k}(gw<+-A=vZ5cyWr!G_=lpSxTfB3|1ls4a z6c~opBt=D_i}yc=bdO^)=k*hkQ)Cs5U;Yp|T{&jsf+U<~n3}$03JKk%r}+@LBtu4V zXVz{g8EoRy%)MOapb<}-@Uem*@2)CdgzmUZL&WmyKq8L#P$d2YJsEE*Vui*!Zv)IB zI z+B+Nr&Y!cpmfRwJA7;w1vhz6olZH%3DQuqj2

    &+&kyYf5&jOMof^sHi`u^Yg5|M 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

    o+8rInK8phoRa|d)G^`rHXe4jBTBM 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¥VtwnD~lFw865Nn0&Kh@+b~_z)E=OScIsV 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 ?^^*y9DfR*%|5J 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


    wwZW)X_dQI#okqOEL+62FzeA<{ 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%0DkA8M;k|NwW4~Ky@Yk*<`8L3%9|a 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�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�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

    `$KU3mOZ3 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

    F}5>-obff@6G(zzf4M3o%ix{KhTaj%{F*DwRABW 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%0DFFH0Ma30KO;di2ca$c=N$;;fG-jG4rv|ptuPV6 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

    jH6!-*3i^KR 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

    E=DD|xWcth) z5bk3@8yrJMMduv6dy9Nf|4DeaU&Jom=gBh+UqvzHh!U%NU4q=>)5Bz*Zpo?tjP2c} z`?Xg4N9{VTrLgDeYYLIaxN12jHO%K5#UsJHuJ?#todpqT zK)*$t-lDrtH79#<-M;qo65#693+n~a=k+P*8>h!r9=ySIMx3;3wA#)yMiB zdji@zr>|hb)57d;g<&1@d6b7{Ui?th?z*TU*xU-Qb?h#ylKb6DsR#x

    Q-jgVZB?^nHc)2nZj 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 brh2J;eJU1WqfJE{m*F-*7$uoG*tAVy-@koCo zP@(J{TTO=&r zZ$&vPG|mp1eov#%E~4)Qy9&7S6F-TX|6Q0r=SczA>YUL@c~LZl#9`@k>b$86oQ?gf z@ko!PwWN67z(sY}7||GUaSaMF<%uSGT*?X(SVR^f3}Lj-18p(hdf5IQ3U6H!e(lu$ zy%Q48tTXy!>nv=WwO3;2 z{*6xItq+F*B0KaPS3{9`6jbbxX((pjET%xq#6PBbgA`towZ!p)s;Vg`lz!_ofe-Ju zbP2u!W@1?LyDl8Q{3MQlI-epOsFi<94^jPbZ@+{-evPy(sv$OlVE%aw&g#X%ZNl+a zBAdbwZLWB`wA;xdLQJn~iPfA8CD{F6r0LWL;NO-_#Nei1DX`Tv&&u-yM?Hr%tuT%= z+())E$n6@$%Gvw&96SGUrW!d-4D`fFl?g!iSsVd8Yy(rp z_=wTIQRkTPCvuip6Ze}zMz8a@!1<{*6JYQmhicUf zu5Qqrep(BM)Ngq{2v_`leu2$cY}`{f zB(yiY;T6(6p~?Ei7}A1gclTNT?-S&6C-Bx^-c_fyJ0jtNAXyp%w%z!(7w)<={p^ku zi$4x3t#WY5`*D7;;TLHWdz5UxJa_f{na3?*P_{wQ>wt#&r&B{-L}eWfYO;(TIrNE= z2mEWyv4$~JU#yftFr^Wbk8E!H8ikHTHs0`iFaIpHMeuyMS%jP>i#0rQp!*|ju&VJU zdA_xUf?b$1&6e)}DNPiPf-{=KZtr2*LnknS_ zV9puN?01GQpJywBI=nA3laQZ^xy0##9k;li;SKVE4_~HHgOIZfPjl*nYz6i!Dz1jnKCNqH*Jtv90+5r;f`AY|iKYSZ`X?0d0&2JqvAlp=uPT_#}yZ0r75sB6dx3J|E2nk|v@rB8+qLKGNzkEzvpuTY|A& z8x*&%h^pycYDLC222(fU1ArYq3-qe=nJs2@font9Fzc?8!=hi;+3=@ji_yd?QXH9= z98*Bg$URFCE~Nk71K1ZP^7xf5TOKz*=L{tEGYSgzQ)cvO)Tb?cW%gXNAWEx7jtT*n z0!!cxhcdf0*E65XY|4X}^6`=&NWt9G1D>94W$7@cQ;NWvw6h7c9-J=h8uN)29PIvP6f--T9%eB_bu>@V1Fcr%N}$Zdm-RpQt)3b8wpWXI z6|dJ0wJUeXSqo=W6cppFoIH-Gm4e&;dI6B%nRG+WDi@mjryE+MjyqMi_q_2a+qi!V z(gc-KFDnjO422Y|<9fZI@l>g!i5@<&B#B`LKMrsTc35mI2E!byrK_{+FWBamE+C)#Y$ylC00Z-rQxXsay@)0GXp2 z7f8Ch#t~J#qnJoFxZ{*fOwh5bDmu>389eb`R^N+FViRe>+<;_%$)rIPK9jz}AYYb0 z2vUFFgdGLkJ;Pe-d;XglNW_X9{{W2nL4@A`mPL^pFxtFS707m+*FIxl9fOX?bN`a; zVH{c3QD5A{5xykE*9{Vj*vNQ(ped)hlwW|gI6TJV?3tk&L;@(UXQ1CP>6Vf{3o+P+ zGN^h_%tA}CSzu@4+Q{A2Dv4NSqQvS%aerve#biz@v=QavSx$+MH+Ft|sKV-v8t7th z#Os4XG~?E}0PouwuV*jp@v4^93PAc2i5A{Pg7}qwavFYZ{qezH*j?{iBn-4Z zbtq3|<6bI1&--(;cXT}H(Ea5RuP<=$uCzOKX|j}A)sB!v3mJiVWDRL+EVQ{eNMo=0 z6zao$DC_BNmWBxTfCj6lY*&?!YMmg2yq@?T4t8WCNH#;!&TKCDwWef);{#R7Z?&W>P^*)#T&pO56jium^4sBUVX$2dnR0(Jbz6Q4O2EFuI(aIKT&*se zeZRaQZ`thVp!j_3h_2)`pXVcI_=WAE_?G@xsNOGmOx6wih&<_LJDyOre=F~|jarkG zb3;tB`T>!qXM^Jvhxn_cgD8N{cB?92tVKW`GfH_xyZ^&m!!m&YIV??@F%kbWy3-^* z@LNH?b}y3mFK-;9&uv=8u^5{b^p!;#5{t#aorVfDUC^lf1FI(P#V!(2gI76GBxA?s z0YkYkqY9w=SpqA+QBS02kXE_ln4{zyc+TKInR25bGR_n*6&6}F{(TaAyVsWdTPO&4y*uY)!WBU$zl0jDIJi`v7#)pJFS$fU!l)a>O2 zBi{?3HD%mLzLvkSC`=comiRYcrdLPp2p6c6vg)zR?jU3+DE}R@L0GPB=^F$FwEnC1 zmvbVZ>j-=};_@*4v=ieSCwM7qtnE8v2Im>H9asqhuD7M37x()!45!`BN6wD|P(k62 zOU@@rp8Y;VKOv{0YZS157z4oSD|@M+wtwQuKIsdBfJb%f8vq`Jia@`E!JgNaOm4UH zz4g34jY94~^ZyhPeM{Ac_3*N8&{AOYCjffZ8|!_sJGZ~Z3<++72|pGsx96@qfyLCSZ5W(weR8xAc1a3cZarT+{tn8@Af;*Nq&>ciI0=60a@ z1CWooxAl!Gdquy#>n4jb7Kk_(=*|F+>bhF7rHRCU$Ttb^EATRAQbf=acOY{b0j0w zMRspRPmo@1sB84?I5hWdzH$Mg|I zZV)<2hB0zilp$$Ht+$s;+k)otV_kJ$ngD{RYxEp2a zqi^c%Y7LHaEJNkq@nai#xXNwp7FcVqB6r3sPi$A&mi{!aOYvIK*vI_(UidXhQ5hX& zxDR{N6fF2cI8H{a}aT}Xg4 zC2I$^kz!Wfj4F1nz=&PQ4XxS9PDMyTJ^WPlU^B2JLV8SBuFnGRPF#h z>G6d)%+Kwc+v;yO9@59mHP8(A8__ z+3i^H0RB3`3!6K2`pkaygYUIjZV}+uSQEK42N3eyXnt2KNIFaXE%`t_#WVBLsghxT z*@znZ`@iW_Q#aql-ZIFHL5?GXPEY1HGi4vCNv;FzFlpfJ=3jd4YnTsPi4ZS>9&W{1 z&E=EjeW*S=Gv=7uOTI94<$U+<5n|7*tH-`@E zNsd_))=jbaL^ZWEl8gK#oTPPa!iONPGmF2uI#dTw+V%k%sW-M)d*7QO=l40~zY)PU z%cp%-q`EE)DW=}%RVJ@E-ilp?W(dHs_I^EX!m1DDD9HD#1_B%c!A~s- zha27HcQr;y(g!+zju8BqYmd9(t7R}Oe}6$}@t@GcQ>&G`yG@MF66}~MTlSNTr}~MJ zU8B-$r&gp&MEd~uAIdAvxPhd)pH=~ol{vSue71#3_rums=#C24{c@RmC4TwKMf#rT zV)pk!)IDyD4f7|}EQo-=D$Qz)xCUm_I@&0KeJJ3Wm$3Ft@gIPfLGnS`BwD!+@ov1p z?^rBWshW2Zs-kgZEe|d_6iYoWdKgFMi(J!$3@1-o-@AX_H!FSauJ0JSa@2AY`L$5l z3#wk4Ij534>?wrF5w`F>4;3cZoik>Xs#@If2sqQM%J;9@pvI7uvd`7w;g+bePdr(m zGQ3+@C2+r~WjQ|HZ3e}VgbTTsWjW-NwSx#rzoFbXy}p)LQVJS>0gyIR?#gQ>{lvAZ zK&&5oVaALi(llOjVTlmH>+9P=331BLmw%-`);^GQBH$wvf{#r;{pBic_R2w z=^6Ng-yHRGF6p7`;1OTcb|G^+iFC18vt(qHwC{(@F_Gl769%E##mZKKAG*@r)o^LC(!Us1kqHhUeGqMK^~>&&sfFIORyB^XQI`yFvkYN~U4l;Y;;6pTDM?L) zN%8iha8p8sQ?aa9m*2CeHDTlq_vGIE`v+$%brc5)Kp_&A+xi`efuEXWx6BtL6a2|x z?k-9^=eFJxxEt-tKhNP1Hq9)2Nz_f?tc610HB81VqSvC#V7n9mKmL0rb;Xx9q*uZadx1j z!Ua1yNXgw0_cG_J9+`86q?s`@$Kc;5d<~D&wnez}-}7%Re}3k8lr8f7Ca_OO6j{nS z)f>HI`ebk8EV6THV?8uI8M-K@p^3&6bhu|pKm9nOoq5|6QaevQUW<8I2RQU?~5Q5^6HMU z{QdgO71Fb^(>QqVmOKhtobmz^Tzjrh73jG#iYl8m>=jM}tfZbS|M)}`mU#qGo_wvC zz>q7hQ=KEaM_DH{zP6H9ck)*!Q&aeGwf-)zQpD#)LJo6htSoZTX=Rl`*Ev-Y?-xGG z7-qeVQ-TkSo5_o!>ZjvvCOOx>kc393wu#LZ#tu#LyZnBQ2>DX2%ofs5Pork@R@M?G z7mHETZLL(IyqpgddP?Yt3TmQxj*_vDUuUZ8_@q}=Oqfc5*EYuujineougEX)i+s^Olcf{8VT0->T_rTL_+0?T;CR0}*(KIuf;eO5Ub$!kLa}BV)114ov_?bt6BdCi5 z;jUIq-NyadFCR$tz)Cs*ZsgBZM09-p`7?m<`HJR2ai($C%==OEMn#h`)fP!GGO9q07lZEeq+JVbZ-_vfdTQjU^a z0E4X*=so{Fv(@URoWv_KV>ISQ2T}Wwln!PHc?_9hod^}jw-_eJEZD-v6ZN?stOu(3m(?!<<0n<3=?;D7b4DYT z{4?a0G+$K+YZco18qB9GM-A`YiqoY2*GJNX;&}GnQBOVCSPF;D%)wd7CIhKuH8BzC zz@{8}1gck(7w%#XrAHf@p$WMj?(|2K6`!@V>+Ob3kG`||?XES<-PfcKi8gv;Ibl?r zye!d-A3nnDgIte{X9}K9>QVm%w>X=pRby53xV$d;ld~)uO;y1?s*#iyn5toZ;X>Z$ zY_od8m;t%G&ym+DSgK9IkSnsU+yFaZeqa4<5@h-p{q3b%{=7RMi+ai<#wBX25sneZ z`AZX$c!5NgjC_YW^bJ|y3s^d&XF+;%*d{;TqGgYxnyc)%cBM#;OO7v>hI7@pavDmk z8!;=daK8`M$r%<=>gSykpAqdR5T_SS9M41)+osp=B8p^sKrWxB27dS+#~uWv2pEZ1 z=)oR3QThwNZSqwCVYJC6C!Kzph^Y=LiBcqowT@z$^HJHN`T0D!Jpmw zUub8nh z5YO~ha^=(-?*Z9_@rnL=#hW%#b(eX@T1)lo@62*zcw!GP$?An`p*n$9w@*hFHyVWLhWma`8ECT za?)-r)l+dcxE-Gyr{qRLw=JzTUqQLz^-gfjeJ@1 zXDPe!X95gy!&%CAjY+7QT+$x6H}-AR$W>5Sf9tm(I_BuH)?_4}Iv2Wexwq^ox-b1U zkqd@H8j;CLB#+GjZFVvYuHd(dv*#X5jU}I@i@8>Fa(JjE$Ej_-7j+p3nIKfyix-m- zPq)6f*L!%p;vPa#3p)nuL|dc`lQF#}3WEX1%~$mhBYDNj7x$=j@aJheVj8OXGOM0{ zo+*a+XNCdl%&?YhY1t`!qii7fC=ypv#R+2eFtgwkCm=?8}85az2n90%d1Mjw4fOKqH|vH z4<8A{v%!mZRt_P2+asi5|8;C#S*2%zTBW@BbRwLDlb?HR9_wV|cJ3-cX7ze9exNTs|H`BM*8uK2LTLh#^A%!5uyruN zTU$LmkrIabYq756Gj6qUPPW5ZYV;RM7U8$yVU~^?8>6d7EnW-}!nK2M529u;^%k#% zLKO*_VD>IKDed<&vX58YUid01_^)r! zWvM&g?BAFE@-_H+)o$MbUFl%;{PrEujfsIFXFKwo&~Ey)PpjgTK~lAK_L(v`d6N5< zXkGHVa*xTbhRMobBI3AT0ZK%%R+1e1Q*>*x?7sZ)}@ zQo6b_c;*@T@BN@)Jzse=o&=Cpp3}@_Y=1O5Sh}LASyQE2bv}5~>R9FVyJ29(roQ>A zkp~j#Yz(c16YTOEeGPKZ+X);0TMX0U=D^l2Fc)WXx~-ggkL=OX_kQ7$RtjVV z$HZCRkGnbt;!yALwu{~{#p~IDxmqj}mdi2DcBLHNC>+~l=X1HHxWOaEn0}3iX402n zZHPvQNl7FMO-^l2s1sgf(0~2P3FhLunpBrgnM$PnGi998wwj*}PdwFvY~hooBKS(! zKTb=dM}qBHHcLMm{j=V7bbb52*>klmaaCIF@1WY>im982HRnJQH<-I7NF1ssXF4 zp=x?@*e+>%?|X^Eh7pa6Marrw#ONIlF3rij9^o85uQGNAgKFgG6~z+tmk@hLo3}=_ zU&A4L9m_fVK|+5e`4aJyH{hTesix`-m4f%mI(s{JJTFVdE~nbm7M@F3i-3YN zZmy5Z5iXjWa(I_UqmgFlYeFHBBJ;Q8U^&IPkzS^r_adnY=|X6=RFPn^B^?DLrz**J zWchzH2wv={a=={P5IN)E-YN=HGeKsb23lYCaXfo#pjN*-FxYxeYt^MI@LEX({fDx!hℑw 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�G&~VZgH?J^!t- z&QOi3AF3F`^)h>xm9~dUc5pn|RinVTRMgtUz%PjOkbYs3Bk`S+@2l*-!IN76bIQ+**R-KtBki&CNTqSa2?M{vcwsRF4_R$Of%A&8)` z?0R`xTgzeYkN~)7p;UbjJ$`4UMvaTG9D~vwGh2QpjqH#9(m~j^^4hG{z=fh~CfJ-6 z;YkZj8Hx-6R<1VkE6XUyZRn^Q(dO`^3^m_pLKgl2sJzX+4d#SqiMZgp)ogK5mQP<6 z9g2r!J>f?JuB}?+5jOaYU8QWkzPbn!#l7V9FTpQwgKRF(EDr8O()euJ}@|w-3@Ly>^PW70w(Rn{I}O8 zVFh9~B!Bmewn2gj(`{sn+L064lC~8x_+Qg!oEV^Cgp?q+jz6K&nlhPMY75d$_&!A; zx#$%I9P`B?-PH4g;Ji=|5e{dao`Ud3n+O!~9ns9}u~$ifEWgi0J1z;rR4q!9ap+!_ z2e`0M7znfNoyx3o^VRS-&z)DZg4jBUPYR9|KO{c)A7>GJ1jJ8>%9@r>cIRq@z1LZ< z*9uL$F>Fr%8gAFMYc}4IZNQeUcm$tT1hR}b+Ubtw7%1BV!5diV$Bm#YBJJ=vm1*1M z?0*LmoI_Id&%TG=FOYu*gU^o+|)dVeqa^JPQeXPM(b0J`b?-8 zOmdKOft23bGHU$vWAywkkC$dvP*M?*@TEnV4x5H0|Mgj&Wj`lFR)r0fLGaq>VL-l< z9fPZlb9UKC#(V<#wO9T#P%s3$258va8*&9fU^tJ`-}QrG%}g!-Be4j7(Ts+2UP)6S zoV=alb)_2rtl8dOH`M?et9M%9z>SBHRL&GiA)ZyyV3Xqs+M+!n)=Bu!Kwbeedtm6< zm-U97YIR^R;V#=a)hZ7Z^E^t(^(&=2{ty`iK1tXKb(Er$++EGZrd%N*iIOi5XbKbka;- zcXA;qBLiX7LR2Ewm_LMK3n+_4Jt^y`oze$3@MH$5mssuPTMpUSf>eaQLn7=`wM#kS zk!KRI@X|f@)kBXy(X_m_aAh^iM4EW5X$t3XC=6@?TI{&REXqnhvOE6we0;vEkaq4AXD{F+_}bYVf?sYT(Wiv^}#zi znr;7w)qD(=3@8ty>8oS#c|jWRbouW&V?CLC!7ips*uNyhuYKXociQCv3aHFEmT!jXTFE8NW~V|q0x6w1*@R}oN8EU zu`b2KWa3jF_D8J@Rac>SywT5Sp_&S*w1AE6ba}3JW$#_CkkEuax09VTD<5%>-?lEX ziJ?y$3b5aD>aU<9Q^^^F6TVGnm8Jo9V$KDN#DSo=pOG?BX2iAFMWp=AXQ2bq|{EO^SO&5B%W6Mvett+8>fUw{mr# zf;L+gjXV>VK=HgwUp%##X#O!&7+lTzu37+*%>&Z5aOK?7G+ViqFX}(}Af~rpBDq5> zjc-s>Y(;Hc{Exclwm=t&-}RScn(z(cJCbV)S4q`fRHW7#u_2INlGoEoI z?e_IIiS^399e#c=GPAHgou?br=y%SXse;xlHLv%qz{neMSX-{m-NgR@-b}6uhE9Y*e@#Yis}782k(cjT)syW{P5BQ(B&xgEESY28YHIe~A;oV+(EB1i`syM45 zxuNTRdO6Pi#AMkKNf>N$>+<5Vl_cgHlZ!85~|gG%IWu!0Md zQi4&e)91CInrp>giV{4Zlb7RAYhF=lt-Q6 z%D7h15|dGZ0)e}m460v={U!9BFo)p0t$%;KnkfXm;hogHz*J*dBS!XUHaQtiN#XdFa%S+S#E4dr%537sX6)k)bu59R)gL)Q(EL=8Ww${~e z6Pv0P>~5I3oLH3w(~6m&k0_@d!AI+dONK@?h!|m^F|_ZR^rdB8;-a(5f2M>`tk9Ax zf(0DH$@@WZ0B>EM$y8k{7h~@}>BvsrHl5dgx5*_YS~Nh?Y%^qMvbv)aJ8{ZwmA+*?9aLKK|@&VuDJr=#s2!uE000?IlooyU=8`jJu7V+u@vVf(ys&$3UM>SiI zrBnK$f#yJK?sxN6YJ!~t%jm61Uzw{(Sz5qFE9deO-d?I=r)alG$fkR2WPiqUSKO1U zb};plt*IukSRCbI{HdrXX_H(zT9Ii%wrS9ULkX+Tz4^(>XLDu{D78?|DRweT0Pwk} z{nf-v378-~kH0R5Z209@X(Hc!fBm4aXfgoGi2+tyoRG$=9|{VQ;~jnL&=9!x8wwWz zsS@%rn^0dQaB)08hM9n2%2e%L#SOWKZ8*3|YT237!`kH!ym5WN%#;Ez<% z)IW6=^yZk7bAKw*DerDQ^#6e}m`Eer(a;##M;cy*YxQ4t4JuK4^JX8o#4EwPiA~dYV13>sN z$iNFR)zitvwupxb4XW3W;ucr9SQ%{`07w8Yf*oL}L-`SMMzzYDbqqPFZeQ;EFTW)& z6WZeu;xh>B;BMah&J{X-K`Er7N58;P-Dy`?CgBt5i)R`P16^4o@7U75bdo1A!`SNC zSx?-X2(N%~I!XE#2{*qOz#85nH7N?025_(r^-TP!jD!BheCp7W0uAdN1%uqVX-rKk zu1tmiwM_$J;J&hYb~E_c^3a?6iNx6d0X^cEh7{0d8qC*qkmk$n)zZxgCuI_S{~ZSW z83OnKX<;ax{(Mrvb{jch`?$-3$b{AOOv%Bu$4CIvL1Z`>m;Y>CyWA{#+nitYpD`&$ zsm~VmImuhb22EF=p!5&mthan2st5c|^-7)5(=E~&OjC`P-d(e$-us94z3~W2M8!m% zBn$~Vb;V&nRljz)1bc4#KQ|$kp?VilS(P`xEVZD2cS|I28+omB@CIZzgCx(H&D-T( zuXM7ZCp2agplfg4Hi<8w6Z_>(?yu*+FAbKHO1sfr@3E#LDM_;bE<~@2UdG%Gc0Z%2 zJribVYq0$G`Cw8fRzEw4H}DT(n*GOj)b59a#RLb*(0f zD3_^dd4ys#&hbAvC>gdr=k9h)t2Ba%C9B&KXZsUBe6##(F`YHQ#0O2* z%2lA5L$|OO6(TN3Znm^WMcID6> zUp<~|$Ovz`O&?VjeDi(9WER9!9#z1C7(Su|m6%RPEsJhOzC9Dz0B3lC(k)*32;A1r z*gP2f2yl^R^KQCHdVtOSY=v=XaiER7Tm{*kp1D%QfzrqY~+$KrhblbE-fma z_7k&c$oq3;o{&6QC@)9KHS|}!Q$q6x z0uF)CTHr+Nb=0YO9TNhZf0n%nd0ObjZOzj!=d-ZDFJEvP30l3c{Sq_t3t(BCr!zyq*QqbA(Nlb*{)Qce z+z_7F@p-P|Yj*y>nl#lgl+P%IAxvE?EqfdsF=nR_CqDu_ZPw-!6w-5?ycFl<<(F^F zdsFQE4+wUv-IY-0)s%9z_>ov;Kbd_BVC#PNXv{R^m_H7>K4B5l5rG~(d1}+hD!DgM zm{yaZF_W8TaZ`vRhFHmB+krj~!aORje2)pv|Ir$8RtVUZF&97a*s^Z>X&HV(CsF(F zf&@mEfAXC~oE-n99bHMAJSnh|uks_QNW&ul23YW;75eqr}&_PkOvt-lo3l4u_WDw^At zF4rBdiate>fL;$0Gi;C(i)|pom~Ag#12)J%AE1{QVoD7-p@Loj`0OQw&=Iz+6pqh& z?_}WPM^KPiO8nUu=MKJH+Vf6;`4&caTbRs`XbKKQA-SU^BJZXjOV0@|MzC-OA7!*;X<)nSC{57m`3nw?*28;~_M!v9`QRf?Mn ze~sZhB>HqhiS}OX-*5nWFPm@~R+p~(YrvWnk=B7qawD7y0l7J3wu`?PJ9hds463Z} zedA}#oz=ig9azZR&xwgxCstpoh>-!OQbzV&6)h~I{$nXvHOK0tmyM>^m z(T!?bBB;g1JjTt;U2YHJlJ7Lxm?FJ=D&xG!+SNgK+iO=9T{nFxzumV&D_9<~l9(bz zQHU!cR^voTh|FQ!+89h&&MJctPO}|jAUNH%K)o)C` z$;29!gCMM?pomYK$8S&?1RW~VT{+^-Z#vyB8=Iz*cJdUySE=10cssG_Nda))QlbFn z3{G52_V+Q5XAO{^Bmm9t9j;R_;*O7(d{tkd-O`UYXW$}5g$?9Tz>)q zSTEj?(kFB2Nf})e-SJh&EYNK!%$bDziXC53Kmj~rxBwP zF*^mL!8M|kfnScKCjR(MGeiRl!~j_X@ds>63_}jfKaaJ376>(mNPCc3H!&ZuWbVVU^!TsU^3$$HePbkL@J* zZZSa&$N0#ngEMW~w;G#9%*H9_`#3*$sjX3)T8A&eyJQ(kQ1#~-*agNLM26t6j{Kxg z3YO9i74{{@U~)Zd|5V40FZJa?BXXKLv5#Y{U*duEogPZB4v!Kcb}6w6*wUY3t|!cG zoHwz%|Jt_wZ2nXE6+MSQj*?i76S02OY{fYegY(xgz8_-3U5R+#n=P`(SQy`Mhh2`C}(#=e(n2QhCRqNt1L+w+$E3vzYX@qz;vORU$L3Pw*8Cq; z-|=PCz<9{Snz>&VjaU>R4&zVO_hYPjI<|qHO5F9CO1kGGMI_F4Oy?%A(pB8y(Z&ZC z6!U}BPg&@Il;uDGqrbr4rwFNFxA4{WP$eyn!AayTQvIIL)D!00ar@TR6waNC8FW>O zFBT;6x^IZ9$E?t`HJ}_fFH&UE87_U|-f`3=9h}A0VaM4t;}aPo_Pk$qUdmLK$PMj@ z2fVl-pkbbAU(hq=O|#y*NOn-jMNDS1t!9 z+63z?3y(cWzef3kY3dOkjllAFgcPOx3x>^P;_SSU!%1r8T#{ha5RJ*ddfaublXWw5 zDyb!BH=*!jT!LBX`qBDv`%{S%Bn&Zds$xBnZcP=0itjWTIK=wuNti7qiJe%$vRn3D zvHJU*8(-r$G*4cc76(yI!nuD{6i5FZJysu`qBF-8$YS~7Us1a@DbSt5Mx>S{X})$U z)bn5))wbZk4icO1qzuK`U<6rB<8#zsNsCCGY(qY|(<|HLJfg>j+Gh24KfhY;df-~Y zleRGEr2n(4 zeA8}jGmgsK`sXZLbKTC4&$y;AZAr_dhMAVwH%qMpW`ywQU0vYM*A3uuv;)6@5V&wsHAYd$&2xP!Pki#|jz*0*a&Y9~KM)?8uNs!l$9P3n$n*4el| zzkfi(o>BhpHu&CS=1kdti$4*3sBmueNT3Z z&NgO2X-qH#o~O#PpO%2xpH$G`((DGYxFE2%6i|RDLK;M@k8IReE}0J!rZI*u^85@8 zmV;L$1E&b$3;zaWdxc!oxkF_Nu&*g!AhP-3&JuB4W?TrS0IP2W_Q9$>s6S2g=Gvoy z9BI5P)AN|c+_d1P%fPVT%Pcl!4>qguZ#V}~>#EQgmC4@(QX*E}6VSVuF#cCa2 zIG~t;rKP$)VXqPINl|8P2;=VfKv&*TSSDkksZf0+prh=YJUqm|weF1Ju|NUz-p}eT z{RqK2MRxFh3e$M?`*t}p$$kA`5g)@^*1D7;=RVP){NJyJ9kxBdfxk6;Yf%xcV*Qo5 zg$5d2Lq<+kK*t9qtdk%li`XrWPVpW*1quMBa!0hTp2HX)zj^{kX=&Q*dz&GrU5)u4 zuL`(>whMjwBFr~x4MPZzXjMpin|X8NmtmKx+-Z#4hit*R@pdpfN2O*T0x|#?s(J>5 z4H4*PR6c9U*%lC`3}TlOrV#L%JD@|ps(^)0%UHY2np^pIyWlHN0t%fO3gIJWe!Bxn zls18tY9U)L2_u1Dfl5UtWp)N<_v10gapF}OM^D`d_u7Y;IF2_ogKTXAM=Lv|?s#Hy zoHP7}t~;R4Dsz`{b*QT$r^b8u?pNIVG(ridoM;>k&x?2v??iztPJSyepUeDwP4zeT z4?e*App+y#L&@M5kt-F2-N-oIfR*#eep{1Wiy08SJj25S!UXlyufqaSKl6Lz z$W%BgGoxw#3?c_!F*#RfaK0`og*@=dv#wcKytjdc@>YXQlcmE!KL(`>$N`6iZy;1u zR(Rm}tKk)Vv1tqJpE!sel7n&N;Sxs2*+z8dzz-{H)!q|&$3@PI8Ce_uxa|dF>vo%Z z>yN031#Qj0xP{f2k|O-WKnXy17TT}BMMo<^Y#h=vD*e&}AXf@#jqI9M7)|RoYag-@ zOankPNq2RB4TJ@m`>{u;R-T>-F_(ykQjH@0mzF|11!Mq{dTBq`{}Te*Qva+6Q|<5} zb#0ZQqN_+q>OVQT(Hqv9oxxwv{=`ZuX&5e-ZXDkGYSWrw=go*5HW>sL()0XzH4TJ} z6TAc%lNn+I=m~gNf4TJ7*om3fL+xQT2O=sMckcyDqiS^^lyLq5y5blHSu$y+eH1_5 z#cei|=8wMTxWjW}G|EDU&HYT(Zq;3h8zg+rZQgrHIM8E7tBfIh8q1OJ8BLPys zKxKT+w~RkBpe{0&kw%x6-@T4Bd@wbxV{X+6*+6N_($3L?24emlHhpWMsdrjF1n@GO zW%0-?WW*2wUp%2*Yrd~dc* zB@p4-!YM;>I!;n7@9pkGoljZKEocGGxxZ4mg5{b4cvw!oXVC&hqDFCAVdO1f*_c=H zAwy5>oYOXM>W*V{;P;!AK$HrH=e}trojkPn*}Nt-LUYb{#*s?~{U+)Co(&(<%`i5?mJn_nm)sw#Iyzhhs( zh>MZHrb;$c)VCOdiZ8$*h#DO!a6Il~V*13-oT4ZeWK;1WqO`txwzSk$SZ3h$OTSvY6KR5dGeXWoe8kvc`w@-8f6wvemN)fPBN@?LvZI~J?w!!a(jtpAh|EL)lQpI%m3D0=59R#-DZ z%%i?TGsYNs$wW2(LX!k-Jl7Bqca45ObogNX+^fi23o4v?gwnr#b845#&(~BVQyck8 zRfsVe=&%(MbAu=SC2(+4t6Zj*C_1TwOGDqBi$ya|LE*B*nEs-Mx?6;;xUuE@pVf%? zAFs%CurEmfLSlq-rn#XXt$r0QrSub&!|UOzc?{@~?yw=`J4|{U3R+6}AZ0*qD6)`P zoEMibeLa>@UwpSjjmTZM$Zz0A)Ns3`k*}}2FOyqFG0gn@dVPm?bIP{-T;NFsfKEmO z54)s2!T)wAuMZ2lZrN|d3wrVsT`OlufN>ZIIZjTE5j;XEPJaqN!zk=7&Tl_$YfE`k zKJRjy%F}gh(^s9GC0N4`4lh3-)sz>@>@^7Sjt4>D@S1cz7?PG$q}TcI-{U|_*y1Dn7cr0vO@~CF z9sLnQ){8Zg@}E~6-;$3%YDfpmyUf{x&jQ!)zDjs1&|z5PIj>?hcNn)lG`RoA-$YZW zPPLe*qVcm9u$mP{(JQ^ldbokNVAW^qRrITrVH?TH@K+eb6cGPMiIGGdOe|%^Bv)ox zHQ$aNYV=gdso+@aDfY(d&?}Z1kxwz|Q6qrcN@Tl4dlb7PwlMc6yjzB(@vF;$AMvr( ztKmG>Mpem+n?S03aGKqm9e?|^H>FOlxzk-osJhLm-B|JcLVl9(YfLG2Xtu)8o8m+p zN8Gv*2XG!ZZ)BdZp~dvLn^X&e_)z4;vYEaVIk z?>@o2nau=hV?!m&l1mnTb%VDp5IP! ze)WRk>vf^}H2ChnJF+FhoC{Sw;p1>nOV*0&jA>)3KfbLYQ_JSrX}y739gx{Y?fdH% zBQ&gq_$GJH@}YJxLqR;{9J1l#zux`a^Y_7R1@@eFnJ}!4Bk5M3Gy{Iemr$`C6UKIr zUR<8|2J$@_Y}Agq)%IHVsfV4D)%}Gcy*9&t8-n{_+z2$@pIK{)fmo}&3W%>vdG&^U z!NWuC=d}9lkw)OwRxTm&M)`pd!BZQl$(wmisWyQ zlamq!diEWaQ$~&v4U?sUK!wlqN%H~FbKPM&?G$R@sfkLN#=>y>ifh&qy6MKO#6i3q z+uBtS1N0zF;f%aDXVc9;J)=|C-j&^;gWnK%V06+_L}N+0jNdtXuYWcR(#v^w6>tLF z(|}hopS^o78&Z5%vtpe1J~h$0m&N_A?Rs#b$RZ9`P2L=)onE!rn@#WjefCi3BR&|! z8QQz1w1#3wb{6L2n<+n|_5JEKOpkoodt0X1%e7_=_MCX}=(GAKXji_6V#skr-PvfE zvaZ4@5$NVq?{mOUq;|35v0%Wq*WlPpq!yK~#VlSkFZt5LxfqV-?;3(W45o?5cbU@TDIak^xT93ry?=^RtL&ZhO*3Ny!F?8=@#6mv?+KJnz&*+B-AH==tduQO<_yS@Q7QTvdIxh$=P zQS!FvK-Fu&Dy=viw|VsE%xCNmCt~~rH{?L}SpwZ$qL`e$LXtyN*`jK<+iT}`EwT$LR2_Wb}E(Oz7)UY{;c;1Vhy}_&qKSNbuDSl0)pqs@DTlDeEf5N%q_gw~^nHW0u8>h844;eH81r81 z9$ff58xWwhSy-wF*Hd`s(k8_Z^~z^`&F=CRu!ApY)Asjche_3weWtSJH=x)$d_`}p zpSN8Xa?QOx&(DQZJH#qsbG-n8>vU4Sm(p8}^`u2u6yfu@l3ZS;6vvTY1%enj(o#^0 zzKg5J0yYJusJ6p!e`nk2LVA*0b;n|*x?B8I?sd`Gzk$Mi@5tVCkPC(U?XI6L-tZM> z=S29NnFSn^p&K_Q6$K(6*MYgHHE&3V(AAWj7+AWpKTHljd%gm|;Lv{|;S*WHV3)e7 zE(UO4=ukGXt{X9~hkm7vm)1t0Vajh_dk@mEN;a#_0qx?|Jj_BHi*9s@cEQ_W0=2NM zwH!S7NfUAZN?V`USA3lCZ+6jD9shOuHF{>>eKlwoIb&~}nL4Ev=|c&d+QHp@HIdGe z(E0Ng`#j#5WB;{QxX=&mnX?=sK&v5Q$(c@UGIwLddD9zvaj426ru*FwKd?UYAUdB- zWNJ+W?%!C=TK=^o2Kx7deI)y#8_W>t=;YKuGfS5Cj7xi!`K` zjEgd1ARd_M5J*l{3If|~v1Bv7XDreS+SHuSl!na>&p3uW%RSB+p7(Wshf41%XHO}U z1A3?6o@p9rQs<>QDR6@Ydeje?=-?`m?m3eRvuQ~HZWE$W{4D-=PXFJAvbRU~`8Wo- zJfKSa4ijeJf+ht^|ACchaV;++58shcP;@M|tb|Nr}^pSg_3&?(e@P3pOc0YhZx>ST&$0(fs~5R$7u5)KS)m0DUU zT<>7s`9H_XG;V|77gsabxc=-?*zkz7H)tR&^S5UigfGAhnf6-+>(yzad>xuNRtl_v zQ=F8yGvN0(wpZ5w1tbfVZqRBBO~0HNu6^XA<@d_2k%u>oibTBRGloB3fM9Gl8@@dS z-LoHk)`KrPHYuEaJqDzNIoKl-iz#RN+6m4_6`Nc*h49r#_>k+s?Tbl9pV^03HxV5laWdS%E{M%Sv_OVN7WHwPLEnO;UOPe-Fnm1LW9B+71F*^Be+b`b*xk*tu)Al_ihH(h-M7D!sJn2G z({P%xPSW$@PzC4?@46t@#l33?Rv=f`>{)Z{I*_-ek$xzILJ+!>ccZBa*e8C1v{3EH zDaBzmL|uq?Rt?hsc&M~(gb$y7-obnNBdulDzF;0U3zyBp=@cuH$TE}pM?NrCPz_-f z>a{5dt8r9)?V9uaEOWTVvcx{>d{fFCcem0j=NJJ1F8a%gEt_>}O zW9ZDi)N-=3_WC_s}n$0Bx`)fA~2KR3relaloaErIdf-fG4WGzW6|AQS62}*og3ZXoT zYcyMPL%$t0NnfLhOdT;*N#2(jcrIDQgtMinBmz~U13fZuy+uKd3_c&2tN5ST39;+7 z@U^BDeUaa*d=y$63r@<*P}kvzN$|wYz_^~>uv*8OlM^c8KCFe3K(1ZWJy1}>?@k`7DIn(V6uTC!r`=5k zm%e|?Jw_s-=nY9*DXw(yL@3Zs+I3J#ZJ13ODLOCD6tiP$#KVaI&+$hqj_R7J+i*vI zlU0Sh1aglC!q|(LlE@jQCdpGq+BlaZtwrf7%~d9TWtUce6@oEJBAFV06zd}OUZ{9V zu<-5ZBErb|#H(FQ25rY<1pqWu*y2-!OM4)ChW=Fg0ppVozBPrgFoQbEXNrR#H_Mph zg!=IbBTl?apXzyqf(`K_UJ&~+2xin;4O&YU(N_2i#WI~`nwO;5#{F>{`)Y^=ad4At zLabIFT0jfN&S}m;Ck2$TEtr3qtgvvR_FJ(>8-Lqg9K% zWA{&0wa>YEdi#>|@oRPgHL9@KKUx$5Cq9Ip^#huQ`IS}mH;*_pRHCC<5g8eadx^dZ zKCuv4(r6Llw&pbX^5Q$1f{K-BhWFS5gEd-emFMaxfLe#?#=m)i@lepml=rsMY0w^n zpy;Wy>f$M5W@<0Td=8 z!W+6n2hUGEXZiK6oiM+SgPK?*$udEDg{57N{0wOkAplzyWL>t*6?9ETUB_^9US+_ zmK(^!Bwa?U&`I4t`C*^kj6SU`@G2)l$T=>Hd3^OG&P#GR zC~(n}Pd+ZMw7@24T@Wug?TW!%{2PvU-lbH32_XZj$=P3Soq}!%`hsX%Hckcazy2?H z@oS@*;ieyGqK`x6yJ^KnSPL9!%GIl*ws7<;tfJWN#?+)OZ&Zr@T4nfY1tc?fV0%_g zJbqlx>-rs1M<^Q~cKq++RhJI&w{EgjSvH;e4|Ay}3Sv3a33ts2ML~atN`hJp3G&@Q zRV9R1lWRa2CtuzLcg_(=PPyxwr{OZ^@*0NF{+<4rYBG1sACh)qc;-dvJ}uyR>AKwl z-DuyQ?^*fwe!f9!nW~lzT*{LT9Vg-a2H7j`eT{09A~F_m&Z}Td(_hYS?ydV=pWCP*zRUPL4#?9jz>(C1%=m|e>->mU=yRx zzdfjO_1Y)D_RpU1G851u@{pSba+P1-lW}d%kD1b+XRmOmsZzhP{2r8HJUy;%e@4?L z`ul-Q0p~1VN6DcdwS;^H(Cy$qb#v{X+2;W5>Vj8;>(fuFL7c$=VUV^m#h4Mu)5m2| z8bW6c{j-EnSbq)@|Mf2Pa#8qTRPDEL+=P=0=e=;Ep@Dt+)hhU*Bm1)+pEP^Ru7Cdi zDaUmJ@p{m@;Rfsu8C~39{e9cb@y?b%XAQybv-X)J^z{@^ugQQrQIPtWVY8`|@^Nw; z_}ewHg!5vzL2zk|`M*$S!Bg;LV?R+^<2aPR4p{0!*d7g96MrjNN){Xn9yiQ_M1J}w zNi;lo*CPIa&_$y%mJTgfxyw{`=j06}Deoq2wu@=cb3#OLw}0 z8#~@$vwLDz3df3f4)yDUD37TS>0K)PisKUs>G5+3ic{7v+Yg7{Kun$1d`stSoAN=7 zDCS6SlABT5EI;(qP_6@SqA~fH%=_Iq_a=_g2T=S^dhZe`Zh_|&!P(D@BOz&hzN}B5 zezg1pTHdPBxhU-`#YPj4NWNd@EFETKX?K}pCq7DiJ!DB@fLx>dWIi9 z$a)6_=_nb^t?U1}wftBPgRzhhX~{`xn&Xl`%gkld7o5pqsOo)pYWVpfWzH$S*!@IR zyOwta#zif8VfaH{&p7ZAlPhG$xW^!BPwUsX<|(3CG?MvU-G8G(ZXTGV+l8xGD=xXt zWa4{Aq@WwyPF*c{r)w}5P3xsh6o|ODXZ+8PjpWHE7voks^XM``0pTC`aKq%iTE%0i zYfc?`g^Cwoe>O7oO#TDP%4S$jioHh7=TqM&K@YMg^ui;0%Q4*{4krMdf7xohV1r#m zj>|+f?ZFOOm2T7}w>6ssPKnt{={LyZW8PpMQk@AD9M}bx` zfGje>R8-gsug^i16mj$^)=bCF`D z@$T6t#mJw96l=Ks$|iAH8P4B&)5>L}=aa+{LIC*>_JUp9OMG8k996(d@Kp_`SxP_^ zc}_lS*XN6xSC9Y4(OIxX(Kb+68tLu^0Yw^VSW=_~MLMJ#>1L%Hq@-I~LAqJG8>G7% zmRxG*+xPnmGuJh9p7We@pT3-*AAb&^0>eq6-7TLa%nHs3|JI}WsHa&^Gunmq7(`Bv zQGJ*8wcMUb#gkHtJ!{C&c%I(bI<=nNs*eqXe0xNvm1K4NTfdEF9N%t|H^Oa>^(0hC z<@N+(ho8Ru2~Bk_GflW9n(VAz7Mk|8W&T^pRmw%8QAO9c9c&cF`)egwlZ_oEuRf`UZrg!EHpJny^E6T|p=8Znz@E3sDa`A3U)LDL#3L}7=m3Di)s zP&WyVP6+ltcJ4U6AvzLZ3u(ZU?*eA9U$Ry@5w4x~tLoCyit8L(mK0VIEJXrgtGNPuB{p zLIyZk(KXtw7Omka{V*rbc-%T!7FRUg2`}U}?)@ge9!^f+QgwPhjY>jfuB7wXuV-riosl+2usV?tozean$BLp3P!{AGHou0mAk$Deg3yWBaFFNm2aBNnki$NZh3A1Cw_*M( zczzW^SBX5O?mt@)`79E)|3m4j$WDd6^~c@HwT$9Zb^F;1aIe=h8n^jpqiR%Xr+5zM zJj4F=wMT4bbpmVuXx&!th@ZF5#pV3(C+Ur3L4Xt9q!r$(wDJ@8Hqaaeuo<_-2ka`S zk0Q!8%NQMT0q|$BgXr+{;?pg}fs!84$vLh;xvmO;5j+d6`|#iFI?#I|KSS1K-7erg z#)R;am^(x)(v=dB8kZ#kQvY)_AFvPu4|Gd>+7j|1&8=- z0}NL>CoimGC*~1R#M1_|`7mOhrc2g&HJ&e3i*Lu0D8;Yq1ei%daqFkz`H&EJaDXT4 zCU1zSpQ_D?BjLU0liR<*EDQ7|roo;%3W{p~DsE(*g5MZ;qWu0ay-@d~NsR6vnC)1r z^nrOS)`aOtOSzwmSw$8TJ`GD@?>|h6Tr-j|5mZ^hQ6E2WySh3mm0|qsT}7`5z7W;5 zU(0%KE=e#5_xXT1%dGTVA3+wY%uVch{POcn-sv7D?@KOQT4(jPUo(s-EDNXDTttT_ z@As-g_g23I(&J~ye4?!I&mWS1esP8=Y`V{1Yr}VYD_<(~2M53-E;i`}VXU3_#p@PU z4`}s6+!|s7VzPgV;I#PvG9o=6ogpZ#A>5w&%OqFJn<}==z&KhQuD(T+Tl>0`wf5e0Lw_+XLfhM3r>Mr&3kF{Y-Ae zfUk~w`97z#Jl^q~8pKLYs`aa0nbw7#w9ELP1XP|NKmQbRYR9%-q!m)vB!M0L=|VRo zZ2gQz!WYT$;5THOl3QJiEkehhv1qxOPO}!AIDmD?gT5(jXwzV>;I<(D+NuH2q{bZx z{mGYq{@`%dVR#B?livbM^gZ_77BSa*D@6VgIWy<~;Ef{pZOQY-jemh2g~F=waf*w* zl4}L;yUPxst?Ay3mHq zbc6!!-_9q=n53R;95q;T*1?+hDOuqZRs95eK77n7!Qo*v^k=^1#nrjOCrQ72rBm34 z<}T5W5<@ye%s&JjL!Us#8+8+p6P1?pA9qbL(xg9*ADd_rV+HRbi4Wxg!~?rwLMKXqh~Ou_tGRci1px~ zMy2?{wDN+0Vgpr<<Z+(=_v(EhKz}Zm$i#U?CcqBpBs{bCW zWOZk61L?bA((zr}qrd+2V*x;SB2A6{)cWb~YP`sO?H}w~G0CnAOtZTenTH}dpAtlT zeaXULp0${y|H@ZH-o&AP?<$Mzqw+ZZ;)4PZ!4yhby{T|9k6_-JlZ*x~I+;W& z?{S&-V!%(*T&TBpRO*gfCpoq5Br_Uczho~xeu1&|LJ)~Xf2B}_p{C#z39kNEWQcF- zLGLz01}njc1gC~= zIbix9R^pb6NrmGu_kBHf9&MRclXK8{2^Ew>WyP6KVp^aRtE1us>tUF|7j}zIU{=S*nsHJmNxhNXLtOpO zmqo4peGA4bQaU$}3)o}}%}pxqv`kqQ*bp%kL> zDb=^Px-oHqG( z;OYmpnk58eNy?@B+T@;u*mZtrsg}_nm9g~n+5R*sWWb#0ExAb@E9Yax@D)VFoNlV@Np@Uq84sicO0|FLZvXWPAFnwzk{)kKgY6c<=#h;8sL$pU z50J-RYtI{WUndVdlwTp#8WcY{M+^pXRys%$s+=)Y7%=!$)p1l1nB%>Rb(oc0_4-MH z-^%F;C+-7Y7+Z=NeWC4&PF3)v2TV#K}O z27cWM1J;{BW@S?dcsHeS$~D)WEm7C~uB8zaS_up~i?|%2etg(~a!c%K>TczZYdp>L zkN~e!5bbLy{k=7B~`oeqrAQR41W)(HH+jp-Q9t)HuOE0HMfq`_d2m zc4lX8`)sHB&x)VPt%XlyqVAN5i&49m?0M`RmwrR8-oZ(pWG@z*;QiXs$Fui*inkQ6 zb!qr->WZw6vIlA#)Y#PRLG%0>ln*&Z^N)>2kgh6JP~zj5gUg`Z`*(>ezeBS5F*wg= zx>I?e$xgic)Agryg;&)W&`c!mnC0#mOv&ZuRRvU_|ETM2w1esSBa(koKO zOtRgH+~ajD6DJ-l(j1?DHk%hK_?F3E>$y|>$)*GrM6(|LuHpUS$Gy4>Vbr_%?wsfJ z!7`2)3w!XR*kw4d#@gfyk$UFrRT}`&u+@tL}|_D{&&NhwGn zU*LDrzTs(LqaRC;gB7Z7e+7S*3&M*!R;rx`qqXKus1k%+ z|GL4JgR120`l!q&UVSJHC+tMCfFIPcI2TD%PE0y+QsYWT+r(Kd^_}mA)-9l6n66B+ z=AJM2g_IS(suLgvde*1yTa+?c82_E2Ur$j47rQHaFK4bfzsDwSJE{k%0cW5mwQQVO za<^R9eU*s`f4I;T{S!Sz_W%9s)}n=VUj#cSqxOXg(8|3tB`*zPKI4q~=sgrLf!AYq z{gqw0T4SQQ7tI2nyWp6&wz?qv^em_Y=!DOaebt|<`qfsy3zFt;^}iGR#cdb6C9X(L z@AG`w@WWaH)1B@+Png#uY7&{(cznbof-{gEzoUkpXsRW4H^*NO%#%C%FfuxT;zlCC}bVOoS+e!QQeeO_7lv{ZhYm%wiY?t}N%>;>zQJ zoBaZyvEx4bIx^mA{k-j=ehe`7Kh@d^x~wj|IR_8{B44Dc8sZy>m@EKPRXxi4Otc2f z_#dz^?heZPt%NsN2{@3~67h=le~Rof7m_@ja97r4n^xC+g(Wb_ga`3oZp}+ItSY&- zWGi!)PUI#=RPa#VUDXhcr`;HcJDNOZ&}G<@BTu6%1ic?Rc(MAD$~i!lPDFH!M4Fw1 zIS$M*dU!0veRAfu8&59WbRQOc(uLDU*&&;^{;hJw4Ue4xFDdem!wBfsFJE-vo3&QI z3>_xuvMYZ2%kF;(-OO#{WXVWLf5$b!Xt@`E>Ka~3CH&LYQy30*R7VA{M7vKi=~J)S;wgJ1T7E)g8p3Eq>?w$i+e|Pcx|z)dYWE887tWCc4&ozJ)TQ2du~K@m~C;(W@Mdcf=!c2;{(A(o5!%05VdJ7+BN;Ph3KM`E+HC_7nh(U#pwM-*rc`D1^OyKMt zM~KoE(8Lct{k0IO@hcxCCGDI- zh;wwsjV3SHN>UL@sQAJcRqH8Jjl70#K~|#03)j&R2bqXZBvo-fjIug!VH0Ez<^gjS zI{vXw#YG|3`-`c1LC^E@>QW-{*cY?qMZ}SE(R+`Rjdtb~+Kd#Z@XMmdbUGj{zpa#e zbN*#__GT^vQ}7zo&-z@>&+qnVQ!TU)G{Uu11zNx00*-z+jaE^ui^ig)RL{ot_Wt5X3ljG+=N&pt3;?mmVheszY)?P4!i-Pu*6hmuyGmDu&O zqjtzj?@rI0B)$i(6J6XoQ&wapo~%r=Om|0#X*}ujM}SAPnQ1<6DfDIkqd~9j==AC1 za^)e(`p495-S{DFvBp=0TK6@o5P!R@gAyw))k-*cpp zf`+2MyTgNvDyU0qW`0`N5GeT3pA;R%DOeRFK{`!yx3(b?~IV*-VDx;H+aFV=I|J$dnHt!Gr+IN&*n$SFcVY_P{~8o&fzfwxcgH#Y*zP4# zJtbRDH`!6A2_#FC(5&mX(PSN9IqAWd1F^R7nBjyon#thL#sXvcd6#v>d?yL_IM>ai z&hsLbF$a^`Oi>GMy&wq#SXI*GIbFNEIzRdDWgqN#F}^Cv6=BdJ#F!SMb)o`p9$Xw2 zetEhKYlZn0BW{&LJ>^aJY*ZIJHZZKio!Y(eq}0jeNlM+0#KdLQU?G4`laRQ5(9HYBHUxf zF5sT>Iu6txAD1Ow9Rv7K{3g8j?S(?jc-eu<660~mWs-3L2V2Xsmiyfq@GV5m{x|3| zti(R4zncgc>~9VO`=o6nP(&jzAP)+H3SFEN0czj>8E-)nF040zg-A!_hcjnHMf(y4 zQ8MJEI?+&mbbLE(nfOgozJ>VA+;ZGO?|M_qH-Ygc`q?)#sIETMGOgIn@x8C9semNQ zb^d#c)A9P#WbEtg6_hrDtUtMk%n9Ugrr;eO;WDaTY=c3WKUV0E-X&C{iHils1ddsYZHJD_l8;bnXkiqoqi%dMq z@!7_X=3P|%@nvx+)tgz~j*=!KrTiGNMFJS+uzTWI{z{Xp(^)0^zps4rJy6>2-eQU% zyHg>JFR2^6B{L+U?*<;$%ADSZX(9Zu067yopU+MFZ;K>I(q8^M(u$ocxrg}VAT872 zxSd9_^aR^N9c!-CDJb-KI#(H&%&uZY!a*E=xO9e)c|VaW3D+KchmY+f^02ehdc=Hl z5;B^jWV7_C*(oxeFm?Z ztk@uVzJ5A(0E1^OBT2GSd7N85 zvE84u@qd0RF6I8M!?x-LRfR9O?YRquyYgJgW2MvV<2I7ROjLe(2HCC;<}UfBFWh2C zmU$ds##l*Y!?*W=h_$QAJFQmODt^G|@-F35>h?apaBj{$u6h-5#P}>+@|iq0fBsSJ z-=NopX)Z-Yh7slUh}&L~VXd9QV}PIPil7pRd1ojGgSUhRwe6ej473(@cadLs{ZpvD z_Ux~Ji>BLW)=E-um8W!3x}iWp(kTiXtC7mIBGul`tmOwKr9%{137w*u-rm=Ep@7B1 zb&2FBht8rRpI4D9EH(1i1G@%oe^2hIlU;T}PaX6{>p<;#enr)4&NHZX2>^`PLcp-# zJ~(K}!}B)Hej5KRP184!#P)ISZQdzFCHcm=SGYXJrTxtSCW~{9`%}06GPtb9ZWE&R zJKUi`|KOYJk4^y78{Un|``KTu#YuX_cVia%-#z|6{FK$OMtxgfMY zAs&j8#xB-PFDf|~e$86N5Xxo~H(=%)*rxh^hP)`as{1@Iu4UKc{inKw6Cg{MYh2fir>;#=Nw_;7`ab6)3A7T?q)YcZ zbDn+BW~*snbVGE8ia!c>GzhCE8!!xFnAzX!c^JbH*^`WbQ=#>mSJ-`A#&_5tWzfTL z>Sytv2IVJ8bRLrJvKs>;;k0iVmnUJ(- z4a|PN+=)yz6|sLTQD*3rv;W?<858qio&E!0z8PMp>{zhqjxCJ}&)O@b=pT7&-*G{%1cR z#XQ?Ml=+6t8ABuXLagI)`LLYxGP7m7X?n^rzl|~T1E_5sj-+C z&*U2(6!cr&cKP%2*=q#Q9D`r=mJ&Gm8_vC>n2D-k(LIre@4!>^^~d+dvOl^H6LR8H zNya?!V6!IG&TBDCcNx};SG*EUMgxLzHDR2UL`{l6gqqlou7~MTUpX$^|9GF$!#DjF zu1mead2uchu~1s7`U1hZL-Ia<7u5L{?)jUm|DErb457CoFeWFl2EpmFo1gKi7IAjs zem`LN!9#HkW%Hqqp?aZCcd4>!yOYm9078Sm+$6a# z36!-cO`6qzIyYH+-?6gWswzuE)@$*>P_;Z}Zy2?43OZ5zW(KvDHqw_r?g{d`bTj+6 zaj1RTTb7iJFFl_k2n&us5oKBU(@(s4us zbL7A~5uP3ycb_}d_L6*MUlh2&93PH)jFVuMLZ!8Xrsw(GgOAHU3VhJ(76u|>#ghA)CnB)oQ95*di6V8i z)fw0>r{3ll3h~?5AvZ)6QbJz>V*#sHS|Fw~i%elOQVlUNk0|R2F3ok;n~wCwNUVYD zPDYSMYxut71C4H7Y9ME&ZnAkUg}qH6rghg_ z^V9jV#Kp6_sm~S1-u~D#*~8M#$+s7;&W>7GaBPY{Il0(NW-VOE3vTLLI62m1V@ftv zbY!?W6ZCTO>4m$?W`Wnr41G7A{Cno6C&h3`~C;M-@sPYKd z;zmQQx7qJihfwnr36n2WbiPP4Ieq>MkdDF?CtTeYb>?>;ZPdHU?>vsR-T9kn)gqfI zmixw^pBSMKY(cHmKuH!f#~m#<^H+%bsiG)OsqIF z1m>73MA@c00A_M>X(7r5{SScnh0z}l5P*_{oE6q5{I!Ok3T1R_&sHSLtp}@*5yLFV zg{iwmVC)plu^}D5l0_K4jhCy%j0YjCUg!&sdWUbdp=D@o{!gc9o!0EI=*w{57PtYQ z$LS7RvA0)X%DE3D0@t{D{rp!j39_@(LR`HO6a3wT{TpHR+ku;YzyQR1W|&N z=C|{p^vgt;t@9i4H6kD$6^@_}5!)douR(M`MAQ}8_L>#wYpA6AHu|zJt@4vt83HR= zQcD9Ex0&s@81FABYwLlOJnq@=JagP*7e$7>D1pPb5x`w8!2<|Vr{P}bi*e7>{}!5| z9R6?>CMGma^#s~>7CV>^*y3tADX9Nkt1|k0-w2A8eCTW487xcsPrEb0N-UnhgHRxQ zLOeGB{;F}Rk35Uvtp)Pc#PdaKnxgNQ$5@fF-5 zoSAR^IylSi*nNq;x~f(pC`iZm#IIWP9_i*kfe!w!9|ZmY#UBu}c?*qCf;Fi05g9cusbpjWr<-W-vikES&iaI&Ds$>-kbwwS=xXxmF+PVtP$_+S$uM)REsc zOx`E5pCs+*=r)vA==4jmLIl5%C1CoU3~@$`)gx;B&ts3@>|LFrpR5!=`6#ZhA09E{ zw$u0;Mfffb|5`IxU%2=!!B=A;njptKz3CIOmyK^db0p&QruLwaIbk)mG&kY%#BQuJ zzaqca=sDkQP^e_2L8X4i#;Ci_06W3iwZ%Y!I*7-;R58xHX|au=S>%C;aNPFGITpT6 z7x{<8iWjvjyI7m`jL;X04E?fItQdbaJb#h+e^hWH!r35xXs}aAJW){TShEecQGAcl zG}&TVE2Fq?Ux%3odN-!VTvYnP>ncQgY1zTD=)f~y&27j%%5ZO{6bdZ+eYpu z`f_6HWd{v+d5RaROMC0>V=H70xu=;Q`G^7YTO?!#b6jjA3@5VPj$g<457`_z?wBe| zZtl#)c>3;`C(wQzCi8*%O zVF|yqysd-K&>!uD8fDf}RRTFWNi8!MYlaA9iBJDSfuhJ7YyQBygDSyeGl~)ahqmLbbFK34s4M&47e29-+*@?$AoBp?^hYr{bMzf zXjhY52cr`!|4Ht{A4dI}oU*r9Zk%ypTVr>Ly#HbOZ&$jh|JmB29~An@qwQ+Bx3}rw z%j2FK-(7=cN69mSjJYlidWfQ5(^RuSp3`4{ii=W229~eL&CHPOZB{Q4fhiC5srB@S zV17=gr+@P^+M2`WwSq{imz9&Ot}LQR(X8QJM&B(b+oAZk-wr0fKKOEb@jlNftRu|H zgQDcfn_YZ_-o<(&sQ=J(dBm~Ydlh;Le%3Yx)*lOP!s%!V^TwIA6Lx|><*gPZJKmnt zTI-0z-UdXOkTUt&t+*07Ecqoi*$+Ji#|%t37w9~-WRe9GF5FZY*S6E<^WF(~4o7ui z-{RD{7A-d2{SvWC=SQ%G%eZCx^(&LNGNVVi1mK_X$-*C=Qis-1a%dbJI)k*Hbx>r2 zM%wC8IpRjKiO}%N%rrk7#}`(r{(P06%vLBrq~ch1XFE%0{V3mZu2Pz|bQ>q%*8a`u z(QSLWs)$DHAFKI-dm1pHlSHzw3M{HIDUd!tUN`}c*-tI2v}MXM0=ZvY3WFZ`M4t9C z@whI)X?XOKTVCw&o$`uGo!%~#Yea}qZ8a38@+`IZvPne>PsQx%1sad)Ny7K}(pgD) z1UX-kD3WYbhXdb+a8W<`+Z?nNq#!pGSc>06ox8hCQQ@=;!^gu9SDQvRo_!T2`MQYa zwW#kV_?hXU^Bm&2oHVI?c$EuWmrcwz;H|kSOMw5${s5BE@B$8ejgACQ`_EpYHUIHV zu*tso=NFcS_FN+<^!{;%CWfdXVRT1@MdbU#SBe!|q{P(rr&kUGh%EoOaH0$i(1U^; z+2#7!m(!5_74FKKc;$kAKVkov0l+@yLXko#tD`jik+&I2vmV5N)46EFWVCl~ZL}tb zP>Xd=irIBjpGjF9Xh?0mc82CaK?-VOt%pM9+T+>!PHOuW{nX*GXTTjcjN2iwAdq6) z-NF32O}-6qu&!D7S{+|oZ2+_geWPq#G|6HU8qCC8)L6I0d>9feQ)Db058b|%%M3(9 zYU(3j=4_`DtE5#hnjkZTxhc%6U$ju<7paZvU{_#? z+HzKsh!H;()V!pAW1ZUa4W+}dgV<-y{SnWzJY{X|LbK?&=n)|@QYW$c_ntYTuW-%r zC`DXkU|atAIW<=f=`<3N4Xb|6E$~Gv zHdE!)HKr6f4?kEl9$&P~c%Jb4y(6#QXatXfZ3gb%@;m0FOmEba%kwzW0y{28Zi;Y2 zfpRC1_;j|ytKUg(GMQg)LSc2vMcwY*on;shOUIoA<~IVKN6as(iwCpNS{!%#tt~F< zNH#+{{r}pm$7-_evVjUN1#25y>Tg5|=Vz&H)Y`Im4|?2FT<>drrK0Yp+3@3l1=Tf~ z6^qAoE-@YojiCl7F%`GVfP!d`X3)1rR=W3-%=-4$jLx$rHgqO++Gs23z9vY(TgjKH zpV{L$d~t@nvZ*T;i!y`0kJv`P6$qa4uA|bHP**ys-2%Hk#S;Sg>@{{Hg}u*0*3r`M zz1)eL<$EW&RX)buj^Q}9J0VW#8x>qsDjPSs{$lAlZrRT*v3~X;1c6yQZva&v{{bG+xLCQfw@okW7=4GY`8_pr_&nD@lt*0jyla zL7Nz7{AO=$eF{2dM7&)LVY4k<`?zX zvlslO{vRj;>B_K!Kb*{t6Vfm6{q&hheJidp_N;*SJ52>~j4~^lixFkH37}!OwX?T5 zsP)O3wbYREV=Uzo6hR%-nBuaj-*EoTel{>DyUdF#Nk*vEu#y?~Kt{~NjasTpa(u5r z?(1wV3h$Fm>*Wmgcun8tDLeeQsBI|zQ9M`c(NuXnl1IMDWL-+VHRzzqu>xC$0;@@5 z=hA8vaDZY}XBnP;NY4EcZOdL>H`rwTb+%7Y<<0ITk_9Q=?34W~yN}KI8SOf0y!9*x zNRyqypM2^Dd8Oo$38kRttbw{Xtp*sYx~szO%tu%*NHVVo*~ZPP2yO_Mk23B*VL7V( z73$g14Gqxl;ib<~G|wZ7=BAcHrIg)E(W+?4P$CBs40}OaxM_dwv<8DzH=Kqb@6_01 znLZf_8x&xxjV(1@b}TSc5!2KiubgeajLdmK7s>uO#9{|gTcH1wS-SWP!hCN*qcj%9 zHgYBIp$%c0O=ZCQEgXPm`JBwpI7FSse6lN(A%c9ez?3+=Fo0RgjAV>8fSJ&<dX<}3wLK)E{EE+gQL0^VEzvD!J^JVBGa{%x_>6JCK)`>FNT^snmdUQ zot)fg*nib@P1d*i6|NouF3)z@z`o2As6%j=&4~ow9~xgy{k6%VKEs0inyHiej7m%w zbO{5)lRT!W0jPu<6zwW$0=$3aIS9R}e+944sekyk{a*@{>gk-~3#c`=`^ zw¥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

    #o8AG)*N_R#RBg9&xb5 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%0Dab=NkNx-$UE!Hb#6?FkKIex(}TErX9M}G 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.)@Hs9j0_1inG_0MXz96A5YoS`yQDEwhc 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