diff --git a/.all-contributorsrc b/.all-contributorsrc index acd1673a4..a1802dc9d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -288,6 +288,15 @@ "code" ] }, + { + "login": "RajeshRk18", + "name": "Rajesh", + "avatar_url": "https://avatars.githubusercontent.com/u/87425610?v=4", + "profile": "https://github.com/RajeshRk18", + "contributions": [ + "code" + ] + }, { "login": "TAdev0", "name": "Tristan", diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 1608069ae..8340fec06 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -3,6 +3,13 @@ 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] - 2024-02-24 + +## Added +- Global Maxpool operator + ## [Unreleased] - 2024-02-21 ## Added @@ -12,7 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## Added - Scatter Nd Operator. -- + ## [Unreleased] - 2023-12-25 ## Added diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 477601b37..c6e3e6c32 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -173,6 +173,7 @@ * [nn.thresholded\_relu](framework/operators/neural-network/nn.thresholded\_relu.md) * [nn.gemm](framework/operators/neural-network/nn.gemm.md) * [nn.grid\_sample](framework/operators/neural-network/nn.grid\_sample.md) + * [nn.global_maxpool](framework/operators/neural-network/nn.global_maxpool.md) * [nn.col2im](framework/operators/neural-network/nn.col2im.md) * [nn.conv_transpose](framework/operators/neural-network/nn.conv\_transpose.md) * [nn.conv](framework/operators/neural-network/nn.conv.md) diff --git a/docs/framework/compatibility.md b/docs/framework/compatibility.md index f3f84ac3f..71b5ea5c9 100644 --- a/docs/framework/compatibility.md +++ b/docs/framework/compatibility.md @@ -125,6 +125,7 @@ You can see below the list of current supported ONNX Operators: | [HammingWindow](operators/tensor/tensor.tensor.hamming_window.md) | :white\_check\_mark: | | [BlackmanWindow](operators/tensor/tensor.tensor.blackman_window.md) | :white\_check\_mark: | | [RandomUniformLike](operators/tensor/tensor.tensor.random_uniform_like.md) | :white\_check\_mark: | +| [GlobalMaxpool](operators/neural-network/nn.global_maxpool.md) | :white\_check\_mark: | | [LabelEncoder](operators/tensor/tensor.label_encoder.md) | :white\_check\_mark: | Current Operators support: **118/156 (75%)** diff --git a/docs/framework/operators/neural-network/README.md b/docs/framework/operators/neural-network/README.md index fc3bfb612..af60daa9a 100644 --- a/docs/framework/operators/neural-network/README.md +++ b/docs/framework/operators/neural-network/README.md @@ -37,6 +37,6 @@ Orion supports currently these `NN` types. | [`nn.gemm`](nn.gemm.md) | Performs General Matrix multiplication. | | [`nn.grid_sample`](nn.grid\_sample.md) | Computes the grid sample of the input tensor and input grid. | | [`nn.col2im`](nn.col2im.md) | Rearranges column blocks back into a multidimensional image | -| [`nn.conv_transpose`](nn.conv\_transpose.md) | Performs the convolution transpose of the input data tensor and weight tensor. | -| [`nn.conv`](nn.conv.md) | Performs the convolution of the input data tensor and weight tensor. | - +| [`nn.conv_transpose`](nn.conv\_transpose.md) | Performs the convolution transpose of the input data tensor and weigth tensor. | +| [`nn.conv`](nn.conv.md) | Performs the convolution of the input data tensor and weigth tensor. | +| [`nn.global_maxpool`](nn.global_maxpool.md) | Computes the global maxpooling of the input tensor. | \ No newline at end of file diff --git a/docs/framework/operators/neural-network/nn.global_maxpool.md b/docs/framework/operators/neural-network/nn.global_maxpool.md new file mode 100644 index 000000000..727907710 --- /dev/null +++ b/docs/framework/operators/neural-network/nn.global_maxpool.md @@ -0,0 +1,61 @@ +#NNTrait::global_maxpool + +```rust + fn global_maxpool( + X: @Tensor, + ) -> Tensor; +``` + +Given an input tensor X, cmputes the global maxpooling. + +## Args + +* `X`(`@Tensor`) - Input tensor of shape (N, C, H, W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. For non image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. + +## Returns + +A `Tensor` of shape (N, C, 1, 1). For non-image case, a `Tensor` of shape (N, C, 1,..,1_n). + +## Example + + ```rust + use orion::operators::nn::NNTrait; + use orion::operators::tensor::{Tensor, TensorTrait}; + +fn example_global_maxpool() -> Tensor { + + let mut shape = ArrayTrait::::new(); + shape.append(1); + shape.append(2); + shape.append(4); + shape.append(2); + + let mut data = ArrayTrait::::new(); + data.append(36); + data.append(63); + data.append(57); + data.append(62); + data.append(13); + data.append(87); + data.append(44); + data.append(6); + data.append(35); + data.append(35); + data.append(75); + data.append(63); + data.append(49); + data.append(11); + data.append(45); + data.append(11); + + let mut X = TensorTrait::new(shape.span(), data.span()); + + return NNTrait::global_maxpool( + @X + ); +} + +>>> [[[87] + [75]]] + +```` \ No newline at end of file diff --git a/nodegen/node/global_maxpool.py b/nodegen/node/global_maxpool.py new file mode 100644 index 000000000..3591db37a --- /dev/null +++ b/nodegen/node/global_maxpool.py @@ -0,0 +1,55 @@ +import numpy as np +from nodegen.node import RunAll +from ..helpers import make_test, to_fp, Tensor, Dtype, FixedImpl, Trait + +def global_maxpool(data: np.ndarray) -> np.ndarray: + spatial_shape = np.ndim(data) - 2 + + result = np.max(data, axis=tuple(range(spatial_shape, spatial_shape + 2))) + + # Add singleton dimensions + for _ in range(spatial_shape): + result = np.expand_dims(result, -1) + + return result + +class Global_maxpool(RunAll): + + @staticmethod + # We test here with fp8x23 implementation. + def fp8x23(): + # Create a random numpy array: + x = np.random.randint(-3, 3, (2, 2, 4, 4)).astype(np.float64) + # Ddefine the expected result: + y = global_maxpool(x) + # Convert the input and output to Tensor class, similar to Orion's Tensor struct: + x = Tensor(Dtype.FP8x23, x.shape, to_fp(x.flatten(), FixedImpl.FP8x23)) + # Convert the floats values in `y` to fixed points with `to_fp` method: + y = Tensor(Dtype.FP8x23, y.shape, to_fp(y.flatten(), FixedImpl.FP8x23)) + + # Define the name of the generated folder. + name = "global_maxpool_fp8x23" + # Invoke `make_test` method to generate corresponding Cairo tests: + make_test( + [x], # List of input tensors. + y, # The expected output result. + "NNTrait::global_maxpool(@input_0)", # The code signature. + name, # The name of the generated folder. + Trait.NN # The trait, if the function is present in either the TensorTrait or NNTrait. + ) + + # We test here with fp16x16 implementation. + @staticmethod + def fp16x16(): + x = np.random.uniform(-3, 3, (2, 2, 4, 4)).astype(np.float64) + y = global_maxpool(x) + + x = Tensor(Dtype.FP16x16, x.shape, to_fp( + x.flatten(), FixedImpl.FP16x16)) + y = Tensor(Dtype.FP16x16, y.shape, to_fp( + y.flatten(), FixedImpl.FP16x16)) + + name = "global_maxpool_fp16x16" + make_test([x], y, "NNTrait::global_maxpool(@input_0)", + name, Trait.NN) + diff --git a/src/operators/nn/core.cairo b/src/operators/nn/core.cairo index 35d318b28..624d114b1 100644 --- a/src/operators/nn/core.cairo +++ b/src/operators/nn/core.cairo @@ -16,8 +16,10 @@ use orion::operators::tensor::core::Tensor; /// gemm - Performs General Matrix multiplication. /// grid_sample - Computes the grid sample of the input tensor and input grid. /// col2im - Rearranges column blocks back into a multidimensional image -/// conv_transpose - Performs the convolution transpose of the input data tensor and weight tensor. -/// conv - Performs the convolution of the input data tensor and weight tensor. +/// conv_transpose - Performs the convolution transpose of the input data tensor and weigth tensor. +/// conv - Performs the convolution of the input data tensor and weigth tensor. +/// global_maxpool - Performs the global maxpooling of the input tensor. + trait NNTrait { /// # NNTrait::relu /// @@ -1304,4 +1306,66 @@ trait NNTrait { mode: Option, padding_mode: Option, ) -> Tensor; + /// #NNTrait::global_maxpool + /// + /// ```rust + /// fn global_maxpool( + /// X: @Tensor, + /// ) -> Tensor; + /// ``` + /// + /// Given an input tensor X, cmputes the global maxpooling. + /// + /// ## Args + /// + /// * `X`(`@Tensor`) - Input tensor of shape (N, C, H, W), where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. For non image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. + /// + /// ## Returns + /// + /// A `Tensor` of shape (N, C, 1, 1). For non-image case, a `Tensor` of shape (N, C, 1,..,1_n). + /// + /// ## Example + /// + /// ```rust + /// use orion::operators::nn::NNTrait; + /// use orion::operators::tensor::{Tensor, TensorTrait}; + /// + /// fn example_global_maxpool() -> Tensor { + /// + /// let mut shape = ArrayTrait::::new(); + /// shape.append(1); + /// shape.append(2); + /// shape.append(4); + /// shape.append(2); + /// + /// let mut data = ArrayTrait::::new(); + /// data.append(36); + /// data.append(63); + /// data.append(57); + /// data.append(62); + /// data.append(13); + /// data.append(87); + /// data.append(44); + /// data.append(6); + /// data.append(35); + /// data.append(35); + /// data.append(75); + /// data.append(63); + /// data.append(49); + /// data.append(11); + /// data.append(45); + /// data.append(11); + /// + /// let mut X = TensorTrait::new(shape.span(), data.span()); + /// + /// return NNTrait::global_maxpool( + /// @X + /// ); + /// } + /// + /// >>> [[[87] + /// [75]]] + /// + /// ```` + fn global_maxpool(X: @Tensor) -> Tensor; } diff --git a/src/operators/nn/functional.cairo b/src/operators/nn/functional.cairo index 45e1c1ec9..48e146933 100644 --- a/src/operators/nn/functional.cairo +++ b/src/operators/nn/functional.cairo @@ -16,3 +16,4 @@ mod conv_transpose; mod depth_to_space; mod space_to_depth; mod conv; +mod global_maxpool; diff --git a/src/operators/nn/functional/global_maxpool.cairo b/src/operators/nn/functional/global_maxpool.cairo new file mode 100644 index 000000000..77e262a71 --- /dev/null +++ b/src/operators/nn/functional/global_maxpool.cairo @@ -0,0 +1,64 @@ +use core::array::ArrayTrait; +use core::array::SpanTrait; +use orion::numbers::NumberTrait; +use core::option::OptionTrait; +use orion::operators::tensor::core::{Tensor, TensorTrait}; +use orion::operators::tensor::math::max_in_tensor::max_in_tensor; + +/// Cf: NNTrait::global_maxpool docstring +fn global_maxpool< + T, + MAG, + impl TNumber: NumberTrait, + impl TTensor: TensorTrait, + impl TPartialOrd: PartialOrd, + impl TCopy: Copy, + impl TDrop: Drop +>( + X: @Tensor +) -> Tensor { + assert((*X).shape.len() == 4, 'Must be a 4D tensor'); + + let mut data = (*X).data; + let mut global_max_vals = ArrayTrait::new(); + + let mut accum = 0; + + let N = (*X).shape.at(0); + let C = (*X).shape.at(1); + let H = (*X).shape.at(2); + let W = (*X).shape.at(3); + + // height * width + let mut area = *H * *W; + + loop { + let mut sub_tensor = ArrayTrait::new(); + + loop { + match data.pop_front() { + Option::Some(data) => { + if accum % area == 0 { + break; + } else { + sub_tensor.append(*data); + accum += 1; + } + }, + Option::None => { break; }, + }; + }; + + let sub_tensor_max = max_in_tensor::(sub_tensor.span()); + + global_max_vals.append(sub_tensor_max); + }; + + let singleton_dim: usize = 1; + + let result = TensorTrait::new( + array![*N, *C, singleton_dim, singleton_dim].span(), global_max_vals.span() + ); + + return result; +} diff --git a/src/operators/nn/implementations/nn_fp16x16.cairo b/src/operators/nn/implementations/nn_fp16x16.cairo index 1c018ade3..8ced1b391 100644 --- a/src/operators/nn/implementations/nn_fp16x16.cairo +++ b/src/operators/nn/implementations/nn_fp16x16.cairo @@ -143,4 +143,8 @@ impl FP16x16NN of NNTrait { ) -> Tensor { functional::conv::conv(X, W, B, auto_pad, dilations, group, kernel_shape, pads, strides) } + + fn global_maxpool(X: @Tensor) -> Tensor { + functional::global_maxpool::global_maxpool(X) + } } diff --git a/src/operators/nn/implementations/nn_fp32x32.cairo b/src/operators/nn/implementations/nn_fp32x32.cairo index a5725eccb..6703c4d6e 100644 --- a/src/operators/nn/implementations/nn_fp32x32.cairo +++ b/src/operators/nn/implementations/nn_fp32x32.cairo @@ -137,4 +137,8 @@ impl FP32x32NN of NNTrait { ) -> Tensor { functional::conv::conv(X, W, B, auto_pad, dilations, group, kernel_shape, pads, strides) } + + fn global_maxpool(X: @Tensor) -> Tensor { + functional::global_maxpool::global_maxpool(X) + } } diff --git a/src/operators/nn/implementations/nn_fp64x64.cairo b/src/operators/nn/implementations/nn_fp64x64.cairo index 01a3b30ad..8d233d61c 100644 --- a/src/operators/nn/implementations/nn_fp64x64.cairo +++ b/src/operators/nn/implementations/nn_fp64x64.cairo @@ -137,4 +137,8 @@ impl FP64x64NN of NNTrait { ) -> Tensor { functional::conv::conv(X, W, B, auto_pad, dilations, group, kernel_shape, pads, strides) } + + fn global_maxpool(X: @Tensor) -> Tensor { + functional::global_maxpool::global_maxpool(X) + } } diff --git a/src/operators/nn/implementations/nn_fp8x23.cairo b/src/operators/nn/implementations/nn_fp8x23.cairo index d80d2c323..0b6495ae5 100644 --- a/src/operators/nn/implementations/nn_fp8x23.cairo +++ b/src/operators/nn/implementations/nn_fp8x23.cairo @@ -139,4 +139,8 @@ impl FP8x23NN of NNTrait { ) -> Tensor { functional::conv::conv(X, W, B, auto_pad, dilations, group, kernel_shape, pads, strides) } + + fn global_maxpool(X: @Tensor) -> Tensor { + functional::global_maxpool::global_maxpool(X) + } } diff --git a/src/operators/nn/implementations/nn_i32.cairo b/src/operators/nn/implementations/nn_i32.cairo index 29a94d288..fab48324e 100644 --- a/src/operators/nn/implementations/nn_i32.cairo +++ b/src/operators/nn/implementations/nn_i32.cairo @@ -130,4 +130,8 @@ impl I32NN of NNTrait { ) -> Tensor { functional::conv::conv(X, W, B, auto_pad, dilations, group, kernel_shape, pads, strides) } + + fn global_maxpool(X: @Tensor) -> Tensor { + functional::global_maxpool::global_maxpool(X) + } } diff --git a/src/operators/nn/implementations/nn_i8.cairo b/src/operators/nn/implementations/nn_i8.cairo index e22de6b43..3131c39b4 100644 --- a/src/operators/nn/implementations/nn_i8.cairo +++ b/src/operators/nn/implementations/nn_i8.cairo @@ -130,4 +130,8 @@ impl I8NN of NNTrait { ) -> Tensor { functional::conv::conv(X, W, B, auto_pad, dilations, group, kernel_shape, pads, strides) } + + fn global_maxpool(X: @Tensor) -> Tensor { + functional::global_maxpool::global_maxpool(X) + } } diff --git a/src/operators/nn/implementations/nn_u32.cairo b/src/operators/nn/implementations/nn_u32.cairo index 7352b7ad9..5e7e70b73 100644 --- a/src/operators/nn/implementations/nn_u32.cairo +++ b/src/operators/nn/implementations/nn_u32.cairo @@ -130,4 +130,8 @@ impl U32NN of NNTrait { ) -> Tensor { functional::conv::conv(X, W, B, auto_pad, dilations, group, kernel_shape, pads, strides) } + + fn global_maxpool(X: @Tensor) -> Tensor { + functional::global_maxpool::global_maxpool(X) + } } diff --git a/src/operators/tensor/core.cairo b/src/operators/tensor/core.cairo index 0d21a4de3..4ad5f8f49 100644 --- a/src/operators/tensor/core.cairo +++ b/src/operators/tensor/core.cairo @@ -5727,9 +5727,7 @@ trait TensorTrait { /// >>> [[[[7299130, 4884492]], [[2339070, 1559536]], [[3448557, 984617]], [[5745934, 3670947]], [[4665989, 3079292]], [[3375288, 948254]], [[3749966, 4911069]], [[1358829, 4368105]]]] /// ``` /// - fn random_uniform_like( - tensor: @Tensor, high: Option, low: Option, seed: Option - ) -> Tensor; + fn random_uniform_like(tensor: @Tensor, high: Option, low: Option, seed: Option) -> Tensor; /// # tensor.label_encoder /// /// ```rust diff --git a/tests/nodes.cairo b/tests/nodes.cairo index 29bebb762..08fed586b 100644 --- a/tests/nodes.cairo +++ b/tests/nodes.cairo @@ -1042,8 +1042,3 @@ mod conv_2D_with_autopad_same; mod conv_2D_with_strides_asymmetric_padding; mod conv_2D_with_strides_with_padding; mod conv_4D_with_padding; -mod label_encoder_fp16x16_3d_default; -mod label_encoder_fp8x23_default; -mod label_encoder_i8_default; -mod label_encoder_i32_default; -mod label_encoder_u32_default; diff --git a/tests/nodes/global_maxpool_fp16x16.cairo b/tests/nodes/global_maxpool_fp16x16.cairo new file mode 100644 index 000000000..fdfd889ed --- /dev/null +++ b/tests/nodes/global_maxpool_fp16x16.cairo @@ -0,0 +1,20 @@ +mod input_0; +mod output_0; + + +use orion::operators::tensor::FP16x16TensorPartialEq; +use orion::operators::nn::NNTrait; +use orion::utils::{assert_eq, assert_seq_eq}; +use orion::operators::nn::FP16x16NN; +use orion::numbers::FixedTrait; + +#[test] +#[available_gas(2000000000)] +fn test_global_maxpool_fp16x16() { + let input_0 = input_0::input_0(); + let z_0 = output_0::output_0(); + + let y_0 = NNTrait::global_maxpool(@input_0); + + assert_eq(y_0, z_0); +} diff --git a/tests/nodes/global_maxpool_fp16x16/input_0.cairo b/tests/nodes/global_maxpool_fp16x16/input_0.cairo new file mode 100644 index 000000000..724221b4e --- /dev/null +++ b/tests/nodes/global_maxpool_fp16x16/input_0.cairo @@ -0,0 +1,79 @@ +use core::array::{ArrayTrait, SpanTrait}; +use orion::operators::tensor::{TensorTrait, Tensor}; +use orion::operators::tensor::{FP16x16Tensor, FP16x16TensorAdd}; +use orion::numbers::{FixedTrait, FP16x16}; + +fn input_0() -> Tensor { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(4); + shape.append(4); + + let mut data = ArrayTrait::new(); + data.append(FP16x16 { mag: 164043, sign: true }); + data.append(FP16x16 { mag: 104646, sign: true }); + data.append(FP16x16 { mag: 55698, sign: false }); + data.append(FP16x16 { mag: 32881, sign: false }); + data.append(FP16x16 { mag: 146034, sign: false }); + data.append(FP16x16 { mag: 169487, sign: false }); + data.append(FP16x16 { mag: 57375, sign: false }); + data.append(FP16x16 { mag: 44731, sign: true }); + data.append(FP16x16 { mag: 19902, sign: false }); + data.append(FP16x16 { mag: 143975, sign: true }); + data.append(FP16x16 { mag: 87285, sign: true }); + data.append(FP16x16 { mag: 169085, sign: true }); + data.append(FP16x16 { mag: 17520, sign: false }); + data.append(FP16x16 { mag: 144204, sign: false }); + data.append(FP16x16 { mag: 125758, sign: true }); + data.append(FP16x16 { mag: 176789, sign: false }); + data.append(FP16x16 { mag: 159947, sign: false }); + data.append(FP16x16 { mag: 87348, sign: true }); + data.append(FP16x16 { mag: 140134, sign: true }); + data.append(FP16x16 { mag: 114653, sign: false }); + data.append(FP16x16 { mag: 148331, sign: false }); + data.append(FP16x16 { mag: 193053, sign: true }); + data.append(FP16x16 { mag: 140887, sign: true }); + data.append(FP16x16 { mag: 107934, sign: false }); + data.append(FP16x16 { mag: 173999, sign: true }); + data.append(FP16x16 { mag: 151312, sign: true }); + data.append(FP16x16 { mag: 187530, sign: true }); + data.append(FP16x16 { mag: 70129, sign: true }); + data.append(FP16x16 { mag: 125123, sign: true }); + data.append(FP16x16 { mag: 14905, sign: false }); + data.append(FP16x16 { mag: 129411, sign: true }); + data.append(FP16x16 { mag: 23476, sign: false }); + data.append(FP16x16 { mag: 92752, sign: true }); + data.append(FP16x16 { mag: 73965, sign: true }); + data.append(FP16x16 { mag: 98412, sign: true }); + data.append(FP16x16 { mag: 94400, sign: false }); + data.append(FP16x16 { mag: 121493, sign: false }); + data.append(FP16x16 { mag: 140013, sign: true }); + data.append(FP16x16 { mag: 140845, sign: false }); + data.append(FP16x16 { mag: 13335, sign: true }); + data.append(FP16x16 { mag: 20479, sign: true }); + data.append(FP16x16 { mag: 155317, sign: true }); + data.append(FP16x16 { mag: 6854, sign: false }); + data.append(FP16x16 { mag: 144641, sign: true }); + data.append(FP16x16 { mag: 12856, sign: true }); + data.append(FP16x16 { mag: 174414, sign: false }); + data.append(FP16x16 { mag: 104363, sign: true }); + data.append(FP16x16 { mag: 118457, sign: false }); + data.append(FP16x16 { mag: 6076, sign: true }); + data.append(FP16x16 { mag: 14842, sign: false }); + data.append(FP16x16 { mag: 21658, sign: true }); + data.append(FP16x16 { mag: 109028, sign: false }); + data.append(FP16x16 { mag: 155965, sign: false }); + data.append(FP16x16 { mag: 101837, sign: false }); + data.append(FP16x16 { mag: 74259, sign: true }); + data.append(FP16x16 { mag: 98164, sign: false }); + data.append(FP16x16 { mag: 192946, sign: true }); + data.append(FP16x16 { mag: 48144, sign: false }); + data.append(FP16x16 { mag: 55205, sign: false }); + data.append(FP16x16 { mag: 130531, sign: false }); + data.append(FP16x16 { mag: 69028, sign: true }); + data.append(FP16x16 { mag: 9247, sign: true }); + data.append(FP16x16 { mag: 179345, sign: false }); + data.append(FP16x16 { mag: 7901, sign: false }); + TensorTrait::new(shape.span(), data.span()) +} diff --git a/tests/nodes/global_maxpool_fp16x16/output_0.cairo b/tests/nodes/global_maxpool_fp16x16/output_0.cairo new file mode 100644 index 000000000..00bd12155 --- /dev/null +++ b/tests/nodes/global_maxpool_fp16x16/output_0.cairo @@ -0,0 +1,19 @@ +use core::array::{ArrayTrait, SpanTrait}; +use orion::operators::tensor::{TensorTrait, Tensor}; +use orion::operators::tensor::{FP16x16Tensor, FP16x16TensorAdd}; +use orion::numbers::{FixedTrait, FP16x16}; + +fn output_0() -> Tensor { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(1); + shape.append(1); + + let mut data = ArrayTrait::new(); + data.append(FP16x16 { mag: 176789, sign: false }); + data.append(FP16x16 { mag: 159947, sign: false }); + data.append(FP16x16 { mag: 174414, sign: false }); + data.append(FP16x16 { mag: 179345, sign: false }); + TensorTrait::new(shape.span(), data.span()) +} diff --git a/tests/nodes/global_maxpool_fp8x23.cairo b/tests/nodes/global_maxpool_fp8x23.cairo new file mode 100644 index 000000000..946215295 --- /dev/null +++ b/tests/nodes/global_maxpool_fp8x23.cairo @@ -0,0 +1,20 @@ +mod input_0; +mod output_0; + + +use orion::operators::tensor::FP8x23TensorPartialEq; +use orion::operators::nn::NNTrait; +use orion::utils::{assert_eq, assert_seq_eq}; +use orion::numbers::FixedTrait; +use orion::operators::nn::FP8x23NN; + +#[test] +#[available_gas(2000000000)] +fn test_global_maxpool_fp8x23() { + let input_0 = input_0::input_0(); + let z_0 = output_0::output_0(); + + let y_0 = NNTrait::global_maxpool(@input_0); + + assert_eq(y_0, z_0); +} diff --git a/tests/nodes/global_maxpool_fp8x23/input_0.cairo b/tests/nodes/global_maxpool_fp8x23/input_0.cairo new file mode 100644 index 000000000..7bedc589c --- /dev/null +++ b/tests/nodes/global_maxpool_fp8x23/input_0.cairo @@ -0,0 +1,79 @@ +use core::array::{ArrayTrait, SpanTrait}; +use orion::operators::tensor::{TensorTrait, Tensor}; +use orion::operators::tensor::{FP8x23Tensor, FP8x23TensorAdd}; +use orion::numbers::{FixedTrait, FP8x23}; + +fn input_0() -> Tensor { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(4); + shape.append(4); + + let mut data = ArrayTrait::new(); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 25165824, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 25165824, sign: true }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 25165824, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 25165824, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 25165824, sign: true }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 25165824, sign: true }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: true }); + data.append(FP8x23 { mag: 8388608, sign: false }); + data.append(FP8x23 { mag: 0, sign: false }); + data.append(FP8x23 { mag: 8388608, sign: true }); + data.append(FP8x23 { mag: 16777216, sign: true }); + TensorTrait::new(shape.span(), data.span()) +} diff --git a/tests/nodes/global_maxpool_fp8x23/output_0.cairo b/tests/nodes/global_maxpool_fp8x23/output_0.cairo new file mode 100644 index 000000000..58b455e1b --- /dev/null +++ b/tests/nodes/global_maxpool_fp8x23/output_0.cairo @@ -0,0 +1,19 @@ +use core::array::{ArrayTrait, SpanTrait}; +use orion::operators::tensor::{TensorTrait, Tensor}; +use orion::operators::tensor::{FP8x23Tensor, FP8x23TensorAdd}; +use orion::numbers::{FixedTrait, FP8x23}; + +fn output_0() -> Tensor { + let mut shape = ArrayTrait::::new(); + shape.append(2); + shape.append(2); + shape.append(1); + shape.append(1); + + let mut data = ArrayTrait::new(); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + data.append(FP8x23 { mag: 16777216, sign: false }); + TensorTrait::new(shape.span(), data.span()) +} diff --git a/tests/operators.cairo b/tests/operators.cairo index b2228224c..67808581c 100644 --- a/tests/operators.cairo +++ b/tests/operators.cairo @@ -5,3 +5,4 @@ mod qlinear_add_test; mod constant_of_shape_test; mod qlinear_leakyrelu_test; mod optional; +mod global_maxpool_test; diff --git a/tests/operators/global_maxpool_test.cairo b/tests/operators/global_maxpool_test.cairo new file mode 100644 index 000000000..fab4a6f2d --- /dev/null +++ b/tests/operators/global_maxpool_test.cairo @@ -0,0 +1,122 @@ +use core::array::{ArrayTrait, SpanTrait}; +use orion::operators::tensor::{TensorTrait, Tensor, U32Tensor}; +use core::debug::PrintTrait; +use orion::operators::nn::core::NNTrait; +use orion::numbers::NumberTrait; +#[test] +#[available_gas(200000000000)] +fn global_maxpool_test() { + let data = array![ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96 + ]; + let a = TensorTrait::::new(array![2, 3, 4, 4].span(), data.span()); + let actual = global_maxpool(@a); + + let expected = TensorTrait::< + u32 + >::new(array![2, 3, 1, 1].span(), array![16, 32, 48, 64, 80, 96].span()); + + let eq = actual.equal(@expected); + + assert(*eq.data[0].into() == 1, 'result[0] == 1'); + assert(*eq.data[1].into() == 1, 'result[1] == 1'); + assert(*eq.data[2].into() == 1, 'result[2] == 1'); + assert(*eq.data[3].into() == 1, 'result[3] == 1'); + assert(*eq.data[4].into() == 1, 'result[4] == 1'); + assert(*eq.data[5].into() == 1, 'result[5] == 1'); +}