use crate::backend::Backend;
use crate::check::TensorCheck;
use crate::{check, Tensor, TensorPrimitive};
pub fn relu<const D: usize, B: Backend>(tensor: Tensor<B, D>) -> Tensor<B, D> {
tensor.relu()
}
pub fn leaky_relu<const D: usize, B: Backend>(
tensor: Tensor<B, D>,
negative_slope: f64,
) -> Tensor<B, D> {
Tensor::from_primitive(TensorPrimitive::Float(B::leaky_relu(
tensor.primitive.tensor(),
crate::ElementConversion::elem(negative_slope),
)))
}
pub fn gelu<const D: usize, B: Backend>(tensor: Tensor<B, D>) -> Tensor<B, D> {
Tensor::from_primitive(TensorPrimitive::Float(B::gelu(tensor.primitive.tensor())))
}
pub fn prelu<const D: usize, B: Backend>(
tensor: Tensor<B, D>,
alpha: Tensor<B, 1>,
) -> Tensor<B, D> {
check!(TensorCheck::check_prelu_shape::<D>(
&tensor.shape(),
&alpha.shape()
));
let weight = if alpha.dims()[0] == 1 {
alpha.reshape([1; D])
} else {
let num_weights = alpha.dims()[0];
let mut s = [1; D];
s[1] = num_weights;
alpha.reshape(s)
};
Tensor::from_primitive(TensorPrimitive::Float(B::prelu(
tensor.primitive.tensor(),
weight.primitive.tensor(),
)))
}
pub fn softmax<const D: usize, B: Backend>(tensor: Tensor<B, D>, dim: usize) -> Tensor<B, D> {
check!(TensorCheck::dim_ops::<D>("softmax", dim));
let tensor = tensor.clone() - tensor.detach().max_dim(dim);
let tensor = tensor.exp();
let tensor_tmp = tensor.clone().sum_dim(dim);
tensor.div(tensor_tmp)
}
pub fn softmin<const D: usize, B: Backend>(tensor: Tensor<B, D>, dim: usize) -> Tensor<B, D> {
check!(TensorCheck::dim_ops::<D>("softmin", dim));
softmax(tensor.neg(), dim)
}
pub fn softplus<const D: usize, B: Backend>(tensor: Tensor<B, D>, beta: f64) -> Tensor<B, D> {
let tensor = (tensor.mul_scalar(beta).exp() + 1).log();
tensor.div_scalar(beta)
}
pub fn quiet_softmax<const D: usize, B: Backend>(tensor: Tensor<B, D>, dim: usize) -> Tensor<B, D> {
check!(TensorCheck::dim_ops::<D>("softmax", dim));
let tensor = tensor.clone() - tensor.detach().max_dim(dim);
let tensor = tensor.exp();
let tensor_tmp = tensor.clone().sum_dim(dim);
tensor.div(tensor_tmp + 1)
}
pub fn log_softmax<const D: usize, B: Backend>(tensor: Tensor<B, D>, dim: usize) -> Tensor<B, D> {
check!(TensorCheck::dim_ops::<D>("log softmax", dim));
let tensor = tensor.clone() - tensor.detach().max_dim(dim);
let tensor_tmp = tensor.clone().exp().sum_dim(dim).log();
tensor.sub(tensor_tmp)
}
pub fn sigmoid<const D: usize, B: Backend>(tensor: Tensor<B, D>) -> Tensor<B, D> {
Tensor::from_primitive(TensorPrimitive::Float(B::sigmoid(
tensor.primitive.tensor(),
)))
}
pub fn hard_sigmoid<const D: usize, B: Backend>(
tensor: Tensor<B, D>,
alpha: f64,
beta: f64,
) -> Tensor<B, D> {
Tensor::from_primitive(TensorPrimitive::Float(B::hard_sigmoid(
tensor.primitive.tensor(),
crate::ElementConversion::elem(alpha),
crate::ElementConversion::elem(beta),
)))
}
pub fn log_sigmoid<const D: usize, B: Backend>(tensor: Tensor<B, D>) -> Tensor<B, D> {
Tensor::from_primitive(TensorPrimitive::Float(B::log_sigmoid(
tensor.primitive.tensor(),
)))
}
pub fn silu<const D: usize, B: Backend>(tensor: Tensor<B, D>) -> Tensor<B, D> {
tensor.clone().mul(sigmoid(tensor))
}
pub fn mish<const D: usize, B: Backend>(tensor: Tensor<B, D>) -> Tensor<B, D> {
tensor.clone().mul(softplus(tensor, 1.0).tanh())
}
pub fn tanh<const D: usize, B: Backend>(tensor: Tensor<B, D>) -> Tensor<B, D> {
tensor.tanh()
}