pub fn scalar_operand<'a, T: crate::TensorScalar>(
tensor: &'a crate::Tensor,
op: &'static str,
backend: impl core::fmt::Display,
) -> crate::Result<&'a crate::TypedTensor<T>> {
tensor.as_typed::<T>().ok_or_else(|| {
crate::Error::unsupported_dtype(
op,
tensor.dtype(),
format!("backend {backend} does not support an externally defined scalar"),
)
})
}
#[macro_export]
macro_rules! with_scalar {
($tensor:expr, all, backend = $backend:expr, op = $op:expr, |$typed:ident| $(-> $ret:ty)? $body:block) => {{
let _ = &$backend;
let _ = &$op;
match $tensor.dtype() {
$crate::DType::F32 => $crate::dispatch::scalar_operand::<f32>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::F64 => $crate::dispatch::scalar_operand::<f64>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::I32 => $crate::dispatch::scalar_operand::<i32>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::I64 => $crate::dispatch::scalar_operand::<i64>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::Bool => $crate::dispatch::scalar_operand::<bool>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::C32 => {
$crate::dispatch::scalar_operand::<$crate::Complex32>($tensor, $op, $backend)
.and_then(|$typed| $body)
}
$crate::DType::C64 => {
$crate::dispatch::scalar_operand::<$crate::Complex64>($tensor, $op, $backend)
.and_then(|$typed| $body)
}
$crate::DType::External(type_id) => Err($crate::Error::unsupported_dtype(
$op,
$crate::DType::External(type_id),
format!(
"backend {} does not support an externally defined scalar",
$backend
),
)),
}
}};
($tensor:expr, numeric, backend = $backend:expr, op = $op:expr, |$typed:ident| $(-> $ret:ty)? $body:block) => {{
match $tensor.dtype() {
$crate::DType::F32 => $crate::dispatch::scalar_operand::<f32>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::F64 => $crate::dispatch::scalar_operand::<f64>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::I32 => $crate::dispatch::scalar_operand::<i32>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::I64 => $crate::dispatch::scalar_operand::<i64>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::C32 => {
$crate::dispatch::scalar_operand::<$crate::Complex32>($tensor, $op, $backend)
.and_then(|$typed| $body)
}
$crate::DType::C64 => {
$crate::dispatch::scalar_operand::<$crate::Complex64>($tensor, $op, $backend)
.and_then(|$typed| $body)
}
$crate::DType::External(type_id) => Err($crate::Error::unsupported_dtype(
$op,
$crate::DType::External(type_id),
format!(
"backend {} does not support an externally defined scalar",
$backend
),
)),
other => Err($crate::Error::unsupported_dtype(
$op,
other,
format!("backend {} does not support this operation/dtype", $backend),
)),
}
}};
($tensor:expr, float_complex, backend = $backend:expr, op = $op:expr, |$typed:ident| $(-> $ret:ty)? $body:block) => {{
match $tensor.dtype() {
$crate::DType::F32 => $crate::dispatch::scalar_operand::<f32>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::F64 => $crate::dispatch::scalar_operand::<f64>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::C32 => {
$crate::dispatch::scalar_operand::<$crate::Complex32>($tensor, $op, $backend)
.and_then(|$typed| $body)
}
$crate::DType::C64 => {
$crate::dispatch::scalar_operand::<$crate::Complex64>($tensor, $op, $backend)
.and_then(|$typed| $body)
}
$crate::DType::External(type_id) => Err($crate::Error::unsupported_dtype(
$op,
$crate::DType::External(type_id),
format!(
"backend {} does not support an externally defined scalar",
$backend
),
)),
other => Err($crate::Error::unsupported_dtype(
$op,
other,
format!("backend {} does not support this operation/dtype", $backend),
)),
}
}};
($tensor:expr, float_only, backend = $backend:expr, op = $op:expr, |$typed:ident| $(-> $ret:ty)? $body:block) => {{
match $tensor.dtype() {
$crate::DType::F32 => $crate::dispatch::scalar_operand::<f32>($tensor, $op, $backend)
.and_then(|$typed| $body),
$crate::DType::F64 => $crate::dispatch::scalar_operand::<f64>($tensor, $op, $backend)
.and_then(|$typed| $body),
other => Err($crate::Error::unsupported_dtype(
$op,
other,
format!("backend {} does not support this operation/dtype", $backend),
)),
}
}};
}
#[macro_export]
macro_rules! with_scalar_read {
($read:expr, all, backend = $backend:expr, op = $op:expr, |$view:ident| $(-> $ret:ty)? $body:block) => {{
let _ = &$backend;
let _ = &$op;
match $read {
$crate::TensorRead::Tensor(tensor) => match tensor.dtype() {
$crate::DType::F32 => $crate::dispatch::scalar_operand::<f32>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::F64 => $crate::dispatch::scalar_operand::<f64>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::I32 => $crate::dispatch::scalar_operand::<i32>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::I64 => $crate::dispatch::scalar_operand::<i64>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::Bool => $crate::dispatch::scalar_operand::<bool>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::C32 => {
$crate::dispatch::scalar_operand::<$crate::Complex32>(tensor, $op, $backend)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
})
}
$crate::DType::C64 => {
$crate::dispatch::scalar_operand::<$crate::Complex64>(tensor, $op, $backend)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
})
}
$crate::DType::External(type_id) => Err($crate::Error::unsupported_dtype(
$op,
$crate::DType::External(type_id),
format!(
"backend {} does not support an externally defined scalar",
$backend
),
)),
},
$crate::TensorRead::View(view) => match view {
$crate::TensorView::F32($view) => $body,
$crate::TensorView::F64($view) => $body,
$crate::TensorView::I32($view) => $body,
$crate::TensorView::I64($view) => $body,
$crate::TensorView::Bool($view) => $body,
$crate::TensorView::C32($view) => $body,
$crate::TensorView::C64($view) => $body,
},
}
}};
($read:expr, numeric, backend = $backend:expr, op = $op:expr, |$view:ident| $(-> $ret:ty)? $body:block) => {{
let read = $read;
let dtype = read.dtype();
match read {
$crate::TensorRead::Tensor(tensor) => match tensor.dtype() {
$crate::DType::F32 => $crate::dispatch::scalar_operand::<f32>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::F64 => $crate::dispatch::scalar_operand::<f64>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::I32 => $crate::dispatch::scalar_operand::<i32>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::I64 => $crate::dispatch::scalar_operand::<i64>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::C32 => {
$crate::dispatch::scalar_operand::<$crate::Complex32>(tensor, $op, $backend)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
})
}
$crate::DType::C64 => {
$crate::dispatch::scalar_operand::<$crate::Complex64>(tensor, $op, $backend)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
})
}
$crate::DType::Bool => Err($crate::Error::unsupported_dtype(
$op,
dtype,
format!("backend {} does not support this operation/dtype", $backend),
)),
$crate::DType::External(type_id) => Err($crate::Error::unsupported_dtype(
$op,
$crate::DType::External(type_id),
format!(
"backend {} does not support an externally defined scalar",
$backend
),
)),
},
$crate::TensorRead::View(view) => match view {
$crate::TensorView::F32($view) => $body,
$crate::TensorView::F64($view) => $body,
$crate::TensorView::I32($view) => $body,
$crate::TensorView::I64($view) => $body,
$crate::TensorView::C32($view) => $body,
$crate::TensorView::C64($view) => $body,
$crate::TensorView::Bool(_) => Err($crate::Error::unsupported_dtype(
$op,
dtype,
format!("backend {} does not support this operation/dtype", $backend),
)),
},
}
}};
($read:expr, float_complex, backend = $backend:expr, op = $op:expr, |$view:ident| $(-> $ret:ty)? $body:block) => {{
let read = $read;
let dtype = read.dtype();
match read {
$crate::TensorRead::Tensor(tensor) => match tensor.dtype() {
$crate::DType::F32 => $crate::dispatch::scalar_operand::<f32>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::F64 => $crate::dispatch::scalar_operand::<f64>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::C32 => {
$crate::dispatch::scalar_operand::<$crate::Complex32>(tensor, $op, $backend)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
})
}
$crate::DType::C64 => {
$crate::dispatch::scalar_operand::<$crate::Complex64>(tensor, $op, $backend)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
})
}
$crate::DType::I32 | $crate::DType::I64 | $crate::DType::Bool => {
Err($crate::Error::unsupported_dtype(
$op,
dtype,
format!("backend {} does not support this operation/dtype", $backend),
))
}
$crate::DType::External(type_id) => Err($crate::Error::unsupported_dtype(
$op,
$crate::DType::External(type_id),
format!(
"backend {} does not support an externally defined scalar",
$backend
),
)),
},
$crate::TensorRead::View(view) => match view {
$crate::TensorView::F32($view) => $body,
$crate::TensorView::F64($view) => $body,
$crate::TensorView::C32($view) => $body,
$crate::TensorView::C64($view) => $body,
$crate::TensorView::I32(_)
| $crate::TensorView::I64(_)
| $crate::TensorView::Bool(_) => Err($crate::Error::unsupported_dtype(
$op,
dtype,
format!("backend {} does not support this operation/dtype", $backend),
)),
},
}
}};
($read:expr, float_only, backend = $backend:expr, op = $op:expr, |$view:ident| $(-> $ret:ty)? $body:block) => {{
let read = $read;
let dtype = read.dtype();
match read {
$crate::TensorRead::Tensor(tensor) => match tensor.dtype() {
$crate::DType::F32 => $crate::dispatch::scalar_operand::<f32>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::F64 => $crate::dispatch::scalar_operand::<f64>(
tensor, $op, $backend,
)
.and_then(|tensor| {
let $view = tensor.as_view();
$body
}),
$crate::DType::I32
| $crate::DType::I64
| $crate::DType::Bool
| $crate::DType::C32
| $crate::DType::C64
| $crate::DType::External(_) => Err($crate::Error::unsupported_dtype(
$op,
dtype,
format!("backend {} does not support this operation/dtype", $backend),
)),
},
$crate::TensorRead::View(view) => match view {
$crate::TensorView::F32($view) => $body,
$crate::TensorView::F64($view) => $body,
$crate::TensorView::I32(_)
| $crate::TensorView::I64(_)
| $crate::TensorView::Bool(_)
| $crate::TensorView::C32(_)
| $crate::TensorView::C64(_) => Err($crate::Error::unsupported_dtype(
$op,
dtype,
format!("backend {} does not support this operation/dtype", $backend),
)),
},
}
}};
}