Skip to content

Commit

Permalink
Merge pull request #598 from canacechan/EyeLike
Browse files Browse the repository at this point in the history
Feat:EyeLike
  • Loading branch information
raphaelDkhn authored Apr 22, 2024
2 parents bac0053 + 5200762 commit 59ebb2f
Show file tree
Hide file tree
Showing 35 changed files with 700 additions and 2 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/framework/operators/tensor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ use orion::operators::tensor::TensorTrait;
| [`tensor.dynamic_quantize_linear`](tensor.dynamic\_quantize\_linear.md) | Computes the Scale, Zero Point and FP32->8Bit conversion of FP32 Input data. |
| [`tensor.scatter_nd`](tensor.scatter\_nd.md) | The output of the operation is produced by creating a copy of the input data, and then updating its value to values specified by updates at specific index positions specified by indices. Its output shape is the same as the shape of data |
| [`tensor.label_encoder`](tensor.label\_encoder.md) | Maps each element in the input tensor to another value. |
| [`tensor.eye_like`](tensor.eye\_like.md) | Generate a 2D tensor (matrix) with ones on the diagonal and zeros everywhere else. Only 2D tensors are supported, i.e. input T1 must be of rank 2. The shape of the output tensor is the same as the input tensor. |

## Arithmetic Operations

Expand Down
44 changes: 44 additions & 0 deletions docs/framework/operators/tensor/tensor.eye_like.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# TensorTrait::eye_like

```rust
fn eye_like(self: @Tensor<T>, k: Option<i32>) -> Tensor<T>;
```

Generate a 2D tensor (matrix) with ones on the diagonal and zeros everywhere else. Only 2D tensors are supported, i.e. input T1 must be of rank 2. The shape of the output tensor is the same as the input tensor. By default, the main diagonal is populated with ones, but attribute 'k' can be used to populate upper or lower diagonals.

## Args

* `self`(`@Tensor<T>`) - 2D input tensor to copy shape, and optionally, type information from.
* `k`(Option<i32>) - (Optional) Index of the diagonal to be populated with ones. Default is 0. If T2 is the output, this op sets T2[i, i+k] = 1. k = 0 populates the main diagonal, k > 0 populates an upper diagonal, and k < 0 populates a lower diagonal.

## Returns

* Output tensor, same shape as input tensor.

## Examples

```rust
use orion::operators::tensor::{FP8x23Tensor, FP8x23TensorAdd};
use core::array::{ArrayTrait, SpanTrait};
use orion::operators::tensor::{TensorTrait, Tensor};
use orion::utils::{assert_eq, assert_seq_eq};
use orion::operators::tensor::FP8x23TensorPartialEq;
use orion::numbers::{FixedTrait, FP8x23};


fn example() -> Tensor<FP8x23> {
let mut shape = ArrayTrait::<usize>::new();
shape.append(2);
shape.append(2);

let mut data = ArrayTrait::new();
data.append(FP8x23 { mag: 16777216, sign: true });
data.append(FP8x23 { mag: 16777216, sign: false });
data.append(FP8x23 { mag: 16777216, sign: true });
data.append(FP8x23 { mag: 16777216, sign: false });
let tensor1 = TensorTrait::new(shape.span(), data.span());

return tensor1.eye_like(Option::Some(0));
}
>>> [1, 0, 0, 1]
```
89 changes: 89 additions & 0 deletions nodegen/node/eye_like.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import numpy as np
from nodegen.node import RunAll
from ..helpers import make_test, to_fp, Tensor, Dtype, FixedImpl, Trait, get_data_statement

def eye_like(data, k=None) -> np.ndarray: # type: ignore
if data is None:
_dtype = np.float32
else:
_dtype = data.dtype
shape = data.shape
if len(shape) == 1:
sh = (shape[0], shape[0])
elif len(shape) == 2:
sh = shape
else:
raise RuntimeError(f"EyeLike only accept 1D or 2D tensors not {shape!r}.")
return np.eye(*sh, k=k, dtype=_dtype) # type: ignore

class Eye_like(RunAll):

@staticmethod
# We test here with fp8x23 implementation.
def fp8x23():
x = np.random.randint(-3, 3, (2, 2)).astype(np.float64)
k = 0
y = eye_like(x, k)

x = Tensor(Dtype.FP8x23, x.shape, to_fp(
x.flatten(), FixedImpl.FP8x23))
y = Tensor(Dtype.FP8x23, y.shape, to_fp(
y.flatten(), FixedImpl.FP8x23))

name = "eye_like_fp8x23"
make_test([x], y, f"input_0.eye_like(Option::Some({k}))", name)

@staticmethod
# We test here with fp16x16 implementation.
def fp16x16():
x = np.random.randint(-3, 3, (4, 7)).astype(np.float64)
k = 3
y = eye_like(x, k)

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 = "eye_like_fp16x16"
make_test([x], y, f"input_0.eye_like(Option::Some({k}))", name)

@staticmethod
# We test here with i8 implementation.
def i8():
x = np.random.randint(0, 6, (5, 3)).astype(np.int8)
k = -2
y = eye_like(x, k)

x = Tensor(Dtype.I8, x.shape, x.flatten())
y = Tensor(Dtype.I8, y.shape, y.flatten())

name = "eye_like_i8"
make_test([x], y, f"input_0.eye_like(Option::Some({k}))", name)

@staticmethod
# We test here with i32 implementation.
def i32():
x = np.random.randint(0, 6, (5, 8)).astype(np.int32)
k = 9
y = eye_like(x, k)

x = Tensor(Dtype.I32, x.shape, x.flatten())
y = Tensor(Dtype.I32, y.shape, y.flatten())

name = "eye_like_i32"
make_test([x], y, f"input_0.eye_like(Option::Some({k}))", name)

@staticmethod
# We test here with u32 implementation.
def u32():
x = np.random.randint(0, 6, (1, 2)).astype(np.uint32)
k = -7
y = eye_like(x, k)

x = Tensor(Dtype.U32, x.shape, x.flatten())
y = Tensor(Dtype.U32, y.shape, y.flatten())

name = "eye_like_u32"
make_test([x], y, f"input_0.eye_like(Option::Some({k}))", name)

49 changes: 47 additions & 2 deletions src/operators/tensor/core.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ impl TensorSerde<T, impl TSerde: Serde<T>, impl TDrop: Drop<T>> of Serde<Tensor<
/// scatter_nd - The output of the operation is produced by creating a copy of the input data, and then updating its value to values specified by updates at specific index positions specified by indices. Its output shape is the same as the shape of data
/// center_crop_pad - Center crop or pad an input to given dimensions.
/// label_encoder - Maps each element in the input tensor to another value.


/// eye_like - Generate a 2D tensor (matrix) with ones on the diagonal and zeros everywhere else. Only 2D tensors are supported, i.e. input T1 must be of rank 2. The shape of the output tensor is the same as the input tensor.
trait TensorTrait<T> {
/// # tensor.new
///
Expand Down Expand Up @@ -6090,6 +6089,52 @@ trait TensorTrait<T> {
values: Option<Span<T>>,
values_tensor: Option<Tensor<T>>
) -> Tensor<T>;
/// # TensorTrait::eye_like
///
/// ```rust
/// fn eye_like(self: @Tensor<T>, k: Option<i32>) -> Tensor<T>;
/// ```
///
/// Generate a 2D tensor (matrix) with ones on the diagonal and zeros everywhere else. Only 2D tensors are supported, i.e. input T1 must be of rank 2. The shape of the output tensor is the same as the input tensor. By default, the main diagonal is populated with ones, but attribute 'k' can be used to populate upper or lower diagonals.
///
/// ## Args
///
/// * `self`(`@Tensor<T>`) - 2D input tensor to copy shape, and optionally, type information from.
/// * `k`(Option<i32>) - (Optional) Index of the diagonal to be populated with ones. Default is 0. If T2 is the output, this op sets T2[i, i+k] = 1. k = 0 populates the main diagonal, k > 0 populates an upper diagonal, and k < 0 populates a lower diagonal.
///
/// ## Returns
///
/// * Output tensor, same shape as input tensor.
///
/// ## Examples
///
/// ```rust
/// use orion::operators::tensor::{FP8x23Tensor, FP8x23TensorAdd};
/// use core::array::{ArrayTrait, SpanTrait};
/// use orion::operators::tensor::{TensorTrait, Tensor};
/// use orion::utils::{assert_eq, assert_seq_eq};
/// use orion::operators::tensor::FP8x23TensorPartialEq;
/// use orion::numbers::{FixedTrait, FP8x23};
///
///
/// fn example() -> Tensor<FP8x23> {
/// let mut shape = ArrayTrait::<usize>::new();
/// shape.append(2);
/// shape.append(2);
///
/// let mut data = ArrayTrait::new();
/// data.append(FP8x23 { mag: 16777216, sign: true });
/// data.append(FP8x23 { mag: 16777216, sign: false });
/// data.append(FP8x23 { mag: 16777216, sign: true });
/// data.append(FP8x23 { mag: 16777216, sign: false });
/// let tensor1 = TensorTrait::new(shape.span(), data.span());
///
/// return tensor1.eye_like(Option::Some(0));
/// }
/// >>> [1, 0, 0, 1]
/// ```
///
fn eye_like(self: @Tensor<T>, k: Option<i32>) -> Tensor<T>;
}

/// Cf: TensorTrait::new docstring
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_bool.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,10 @@ impl BoolTensor of TensorTrait<bool> {
) -> Tensor<bool> {
panic(array!['not supported!'])
}

fn eye_like(self: @Tensor<bool>, k: Option<i32>) -> Tensor<bool> {
panic(array!['not supported!'])
}
}

/// Implements partial equal for two `Tensor<bool>` using the `PartialEq` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_complex64.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,10 @@ impl Complex64Tensor of TensorTrait<complex64> {
) -> Tensor<complex64> {
panic(array!['not supported!'])
}

fn eye_like(self: @Tensor<complex64>, k: Option<i32>) -> Tensor<complex64> {
panic(array!['not supported!'])
}
}

/// Implements addition for `Tensor<complex64>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_fp16x16.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,10 @@ impl FP16x16Tensor of TensorTrait<FP16x16> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<FP16x16>, k: Option<i32>) -> Tensor<FP16x16> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<FP16x16>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_fp16x16wide.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,10 @@ impl FP16x16WTensor of TensorTrait<FP16x16W> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<FP16x16W>, k: Option<i32>) -> Tensor<FP16x16W> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<FP16x16W>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_fp32x32.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,10 @@ impl FP32x32Tensor of TensorTrait<FP32x32> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<FP32x32>, k: Option<i32>) -> Tensor<FP32x32> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<FP32x32>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_fp64x64.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,10 @@ impl FP64x64Tensor of TensorTrait<FP64x64> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<FP64x64>, k: Option<i32>) -> Tensor<FP64x64> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<FP64x64>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_fp8x23.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,10 @@ impl FP8x23Tensor of TensorTrait<FP8x23> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<FP8x23>, k: Option<i32>) -> Tensor<FP8x23> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<FP8x23>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_fp8x23wide.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,10 @@ impl FP8x23WTensor of TensorTrait<FP8x23W> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<FP8x23W>, k: Option<i32>) -> Tensor<FP8x23W> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<FP8x23W>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_i32.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,10 @@ impl I32Tensor of TensorTrait<i32> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<i32>, k: Option<i32>) -> Tensor<i32> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<i32>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_i8.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,10 @@ impl I8Tensor of TensorTrait<i8> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<i8>, k: Option<i32>) -> Tensor<i8> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<i8>` using the `Add` trait.
Expand Down
4 changes: 4 additions & 0 deletions src/operators/tensor/implementations/tensor_u32.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,10 @@ impl U32Tensor of TensorTrait<u32> {
self, default_list, default_tensor, keys, keys_tensor, values, values_tensor
)
}

fn eye_like(self: @Tensor<u32>, k: Option<i32>) -> Tensor<u32> {
math::eye_like::eye_like(self, k)
}
}

/// Implements addition for `Tensor<u32>` using the `Add` trait.
Expand Down
1 change: 1 addition & 0 deletions src/operators/tensor/math.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ mod hann_window;
mod hamming_window;
mod blackman_window;
mod scatter_nd;
mod eye_like;
61 changes: 61 additions & 0 deletions src/operators/tensor/math/eye_like.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use orion::numbers::fixed_point::core::FixedTrait;
use orion::numbers::NumberTrait;
use orion::operators::tensor::core::{Tensor, TensorTrait};

fn eye_like<
T,
MAG,
impl TTensor: TensorTrait<T>,
impl TNumber: NumberTrait<T, MAG>,
impl TAdd: Add<T>,
impl TSub: Sub<T>,
impl TMul: Mul<T>,
impl TDiv: Div<T>,
impl TTensorAdd: Add<Tensor<T>>,
impl TPartialOrd: PartialOrd<T>,
impl TAddEq: AddEq<T>,
impl TCopy: Copy<T>,
impl TDrop: Drop<T>,
>(
self: @Tensor<T>, k: Option<i32>
) -> Tensor<T> {
assert((*self.shape).len() == 2 || (*self.shape).len() == 1, 'Unexpected shape.');
let mut shape = *self.shape;
if (*self.shape).len()==1 {
shape = (array![*(*self.shape).at(0), *(*self.shape).at(0)]).span();
};
let M = *shape.at(1);
let K = match k {
Option::Some(val) => val,
Option::None => 0,
};
let len = *(shape.at(0)) * (*(shape.at(1)));
let mut i: usize = 0;
let mut arr: Array<T> = array![];
while i != len {
arr.append(NumberTrait::zero());
i += 1;
};
if (K >= M.try_into().unwrap()) {
return TensorTrait::<T>::new(shape, arr.span());
};
let mut j: usize = 0;
if (K < 0){
j = (-(K)).try_into().unwrap() * M;
} else {
j = K.try_into().unwrap();
};
let end: usize = (M.try_into().unwrap() - K).try_into().unwrap() * M;
i = 0;
arr = array![];
while i != len {
if (i == j && j < end) {
arr.append(NumberTrait::one());
j += (M + 1);
} else {
arr.append(NumberTrait::zero());
};
i += 1;
};
return TensorTrait::<T>::new(shape, arr.span());
}
Loading

0 comments on commit 59ebb2f

Please sign in to comment.