#[macro_use]
use crate::stdlib::*;
use nalgebra::{ArrayStorage, Const, DVector, Matrix3, Matrix4, Scalar};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
#[derive(Debug)]
pub struct ConvertMatPassthrough {
pub out: Ref<Value>,
}
impl MechFunctionImpl for ConvertMatPassthrough {
fn solve(&self) {}
fn out(&self) -> Value {
self.out.borrow().clone()
}
fn to_string(&self) -> String {
format!("{:#?}", self)
}
}
#[cfg(feature = "compiler")]
impl MechFunctionCompiler for ConvertMatPassthrough {
fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
let name = format!("ConvertMatPassthrough");
compile_nullop!(
name,
self.out,
ctx,
FeatureFlag::Builtin(FeatureKind::Convert)
);
}
}
#[derive(Debug)]
pub struct ConvertMatToMat2<TFrom, TTo, FromMat, ToMat> {
pub arg: Ref<FromMat>,
pub out: Ref<ToMat>,
_marker: PhantomData<(TFrom, TTo)>,
}
impl<TFrom, TTo, FromMat, ToMat> MechFunctionImpl for ConvertMatToMat2<TFrom, TTo, FromMat, ToMat>
where
Ref<ToMat>: ToValue,
TFrom: LosslessInto<TTo> + Debug + Scalar + Clone,
TTo: Debug + Scalar,
for<'a> &'a FromMat: IntoIterator<Item = &'a TFrom>,
for<'a> &'a mut ToMat: IntoIterator<Item = &'a mut TTo>,
FromMat: Debug,
ToMat: Debug,
{
fn solve(&self) {
let arg_ptr = self.arg.as_ptr();
let out_ptr = self.out.as_mut_ptr();
unsafe {
let arg_ref: &FromMat = &*arg_ptr;
let out_ref: &mut ToMat = &mut *out_ptr;
for (dst, src) in (&mut *out_ref).into_iter().zip((&*arg_ref).into_iter()) {
*dst = src.clone().lossless_into();
}
}
}
fn out(&self) -> Value {
self.out.to_value()
}
fn to_string(&self) -> String {
format!("{:#?}", self)
}
}
#[cfg(feature = "compiler")]
impl<TFrom, TTo, FromMat, ToMat> MechFunctionCompiler
for ConvertMatToMat2<TFrom, TTo, FromMat, ToMat>
where
TFrom: ConstElem + CompileConst + AsValueKind,
TTo: ConstElem + CompileConst + AsValueKind,
FromMat: CompileConst + ConstElem + AsValueKind,
ToMat: CompileConst + ConstElem + AsValueKind,
{
fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
let name = format!(
"ConvertMatToMat2<{},{}>",
FromMat::as_value_kind(),
ToMat::as_value_kind()
);
compile_unop!(
name,
self.out,
self.arg,
ctx,
FeatureFlag::Builtin(FeatureKind::Convert)
);
}
}
fn create_convert_mat_to_mat<TFrom, TTo>(
v: Matrix<TFrom>,
shape: &[usize],
) -> MResult<Box<dyn MechFunction>>
where
#[cfg(feature = "matrix1")]
Ref<na::Matrix1<TTo>>: ToValue,
#[cfg(feature = "matrix2")]
Ref<na::Matrix2<TTo>>: ToValue,
#[cfg(feature = "matrix3")]
Ref<na::Matrix3<TTo>>: ToValue,
#[cfg(feature = "matrix4")]
Ref<na::Matrix4<TTo>>: ToValue,
#[cfg(feature = "matrix3x2")]
Ref<na::Matrix3x2<TTo>>: ToValue,
#[cfg(feature = "matrix2x3")]
Ref<na::Matrix2x3<TTo>>: ToValue,
#[cfg(feature = "row_vector2")]
Ref<na::RowVector2<TTo>>: ToValue,
#[cfg(feature = "row_vector3")]
Ref<na::RowVector3<TTo>>: ToValue,
#[cfg(feature = "row_vector4")]
Ref<na::RowVector4<TTo>>: ToValue,
#[cfg(feature = "vector2")]
Ref<na::Vector2<TTo>>: ToValue,
#[cfg(feature = "vector3")]
Ref<na::Vector3<TTo>>: ToValue,
#[cfg(feature = "vector4")]
Ref<na::Vector4<TTo>>: ToValue,
#[cfg(feature = "vectord")]
Ref<na::DVector<TTo>>: ToValue,
#[cfg(feature = "row_vectord")]
Ref<na::RowDVector<TTo>>: ToValue,
#[cfg(feature = "matrixd")]
Ref<na::DMatrix<TTo>>: ToValue,
TFrom: LosslessInto<TTo> + Debug + Scalar + Clone + ConstElem + CompileConst + AsValueKind,
TTo: Debug + Scalar + Default + ConstElem + CompileConst + AsValueKind,
{
let zero = TTo::default();
match v {
#[cfg(feature = "matrix1")]
Matrix::Matrix1(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix1::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "matrix2")]
Matrix::Matrix2(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix2::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "matrix3")]
Matrix::Matrix3(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix3::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "matrix4")]
Matrix::Matrix4(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix4::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "matrix3x2")]
Matrix::Matrix3x2(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix3x2::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "matrix2x3")]
Matrix::Matrix2x3(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix2x3::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "row_vector2")]
Matrix::RowVector2(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowVector2::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "row_vector3")]
Matrix::RowVector3(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowVector3::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "row_vector4")]
Matrix::RowVector4(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowVector4::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "vector2")]
Matrix::Vector2(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Vector2::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "vector3")]
Matrix::Vector3(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Vector3::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "vector4")]
Matrix::Vector4(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Vector4::from_element(zero)),
_marker: PhantomData,
})),
#[cfg(feature = "vectord")]
Matrix::DVector(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DVector::from_element(shape[0], zero)),
_marker: PhantomData,
})),
#[cfg(feature = "row_vectord")]
Matrix::RowDVector(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowDVector::from_element(shape[1], zero)),
_marker: PhantomData,
})),
#[cfg(feature = "matrixd")]
Matrix::DMatrix(v) => Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DMatrix::from_element(shape[0], shape[1], zero)),
_marker: PhantomData,
})),
_ => Err(MechError::new(FeatureNotEnabledError, None).with_compiler_loc()),
}
}
fn create_reshape_mat_to_mat<TFrom, TTo>(
v: Matrix<TFrom>,
shape: &[usize],
) -> MResult<Box<dyn MechFunction>>
where
#[cfg(feature = "matrix1")]
Ref<na::Matrix1<TTo>>: ToValue,
#[cfg(feature = "matrix2")]
Ref<na::Matrix2<TTo>>: ToValue,
#[cfg(feature = "matrix3")]
Ref<na::Matrix3<TTo>>: ToValue,
#[cfg(feature = "matrix4")]
Ref<na::Matrix4<TTo>>: ToValue,
#[cfg(feature = "matrix3x2")]
Ref<na::Matrix3x2<TTo>>: ToValue,
#[cfg(feature = "matrix2x3")]
Ref<na::Matrix2x3<TTo>>: ToValue,
#[cfg(feature = "row_vector2")]
Ref<na::RowVector2<TTo>>: ToValue,
#[cfg(feature = "row_vector3")]
Ref<na::RowVector3<TTo>>: ToValue,
#[cfg(feature = "row_vector4")]
Ref<na::RowVector4<TTo>>: ToValue,
#[cfg(feature = "vector2")]
Ref<na::Vector2<TTo>>: ToValue,
#[cfg(feature = "vector3")]
Ref<na::Vector3<TTo>>: ToValue,
#[cfg(feature = "vector4")]
Ref<na::Vector4<TTo>>: ToValue,
#[cfg(feature = "vectord")]
Ref<na::DVector<TTo>>: ToValue,
#[cfg(feature = "row_vectord")]
Ref<na::RowDVector<TTo>>: ToValue,
#[cfg(feature = "matrixd")]
Ref<na::DMatrix<TTo>>: ToValue,
TFrom: LosslessInto<TTo> + Debug + Scalar + Clone + ConstElem + CompileConst + AsValueKind,
TTo: Debug + Scalar + Default + ConstElem + CompileConst + AsValueKind,
{
let zero = TTo::default();
let dims = v.shape();
match (v, shape[0], shape[1]) {
#[cfg(all(feature = "matrix2", feature = "row_vector4"))]
(Matrix::Matrix2(v), 1, 4) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowVector4::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix2", feature = "vector4"))]
(Matrix::Matrix2(v), 4, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Vector4::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix3", feature = "row_vectord"))]
(Matrix::Matrix3(v), 1, 9) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowDVector::from_element(9, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix3", feature = "vectord"))]
(Matrix::Matrix3(v), 9, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DVector::from_element(9, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix4", feature = "row_vectord"))]
(Matrix::Matrix4(v), 1, 16) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowDVector::from_element(16, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix4", feature = "vectord"))]
(Matrix::Matrix4(v), 16, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DVector::from_element(16, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix3x2", feature = "row_vectord"))]
(Matrix::Matrix3x2(v), 1, 6) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowDVector::from_element(6, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix3x2", feature = "vectord"))]
(Matrix::Matrix3x2(v), 6, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DVector::from_element(6, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix3x2", feature = "matrix2x3"))]
(Matrix::Matrix3x2(v), 2, 3) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix2x3::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix2x3", feature = "row_vectord"))]
(Matrix::Matrix2x3(v), 1, 6) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowDVector::from_element(6, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix2x3", feature = "vectord"))]
(Matrix::Matrix2x3(v), 6, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DVector::from_element(6, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrix2x3", feature = "matrix3x2"))]
(Matrix::Matrix2x3(v), 3, 2) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix3x2::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vector2", feature = "row_vector2"))]
(Matrix::Vector2(v), 1, 2) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowVector2::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vector3", feature = "row_vector3"))]
(Matrix::Vector3(v), 1, 3) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowVector3::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vector4", feature = "row_vector4"))]
(Matrix::Vector4(v), 1, 4) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowVector4::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vector4", feature = "matrix2"))]
(Matrix::Vector4(v), 2, 2) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix2::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vector2", feature = "vector2"))]
(Matrix::RowVector2(v), 2, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Vector2::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vector3", feature = "vector3"))]
(Matrix::RowVector3(v), 3, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Vector3::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vector4", feature = "vector4"))]
(Matrix::RowVector4(v), 4, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Vector4::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vector4", feature = "matrix2"))]
(Matrix::RowVector4(v), 2, 2) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix2::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vectord", feature = "matrix3"))]
(Matrix::RowDVector(v), 3, 3) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix3::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vectord", feature = "matrix4"))]
(Matrix::RowDVector(v), 4, 4) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix4::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vectord", feature = "matrix2x3"))]
(Matrix::RowDVector(v), 2, 3) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix2x3::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vectord", feature = "matrix3x2"))]
(Matrix::RowDVector(v), 3, 2) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix3x2::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vectord", feature = "vectord"))]
(Matrix::RowDVector(v), n, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DVector::from_element(n, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "row_vectord", feature = "matrixd"))]
(Matrix::RowDVector(v), n, m) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DMatrix::from_element(n, m, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vectord", feature = "matrix3"))]
(Matrix::DVector(v), 3, 3) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix3::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vectord", feature = "matrix4"))]
(Matrix::DVector(v), 4, 4) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix4::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vectord", feature = "matrix3x2"))]
(Matrix::DVector(v), 3, 2) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix3x2::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vectord", feature = "matrix2x3"))]
(Matrix::DVector(v), 2, 3) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(Matrix2x3::from_element(zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vectord", feature = "row_vectord"))]
(Matrix::DVector(v), 1, n) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowDVector::from_element(n, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "vectord", feature = "matrixd"))]
(Matrix::DVector(v), n, m) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DMatrix::from_element(n, m, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrixd", feature = "vectord"))]
(Matrix::DMatrix(v), n, 1) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DVector::from_element(n, zero)),
_marker: PhantomData,
}));
}
#[cfg(all(feature = "matrixd", feature = "row_vectord"))]
(Matrix::DMatrix(v), 1, n) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(RowDVector::from_element(n, zero)),
_marker: PhantomData,
}));
}
#[cfg(feature = "matrixd")]
(Matrix::DMatrix(v), n, m) => {
return Ok(Box::new(ConvertMatToMat2 {
arg: v,
out: Ref::new(DMatrix::from_element(n, m, zero)),
_marker: PhantomData,
}));
}
_ => {
return Err(MechError::new(
ReshapeError {
original: (dims[0], dims[1]),
requested: (shape[0], shape[1]),
},
None,
)
.with_compiler_loc());
}
}
}
macro_rules! impl_conversion_mat_to_mat_fxn {
(
$(
$src:tt, $src_string:tt => [ $( $dst:tt, $dst_string:tt ),+ $(,)? ]
);+ $(;)?
) => {
pub fn impl_conversion_mat_to_mat_fxn(
source_value: Value,
target_kind: ValueKind
) -> MResult<Box<dyn MechFunction>> {
if let (Value::MatrixValue(source_matrix), ValueKind::Matrix(target_element_kind, target_dims)) = (&source_value, &target_kind) {
let source_shape = source_matrix.shape();
let output_shape = if target_dims.is_empty() {
source_shape.clone()
} else if source_shape == *target_dims {
target_dims.clone()
} else if source_shape[0] * source_shape[1] == target_dims[0] * target_dims[1] {
target_dims.clone()
} else {
return Err(MechError::new(
ReshapeError { original: (source_shape[0], source_shape[1]), requested: (target_dims[0], target_dims[1]) },
None,
).with_compiler_loc());
};
let converted = source_matrix
.as_vec()
.into_iter()
.map(|value| {
if matches!(target_element_kind.as_ref(), ValueKind::Any) {
return Ok(value.clone());
}
match value {
Value::Empty | Value::EmptyKind(_) if matches!(target_element_kind.as_ref(), ValueKind::Option(_)) => Ok(Value::Empty),
Value::Empty | Value::EmptyKind(_) => Err(MechError::new(
UnsupportedConversionError { from: value.kind(), to: target_element_kind.as_ref().clone() },
None,
).with_compiler_loc()),
other => other
.convert_to(target_element_kind.as_ref())
.ok_or_else(|| MechError::new(
UnsupportedConversionError { from: other.kind(), to: target_element_kind.as_ref().clone() },
None,
).with_compiler_loc()),
}
})
.collect::<MResult<Vec<Value>>>()?;
let out = matrix_value_to_concrete_matrix(converted, target_element_kind.as_ref(), &output_shape)?;
return Ok(Box::new(ConvertMatPassthrough { out: Ref::new(out) }));
}
if let ValueKind::Matrix(target_element_kind, target_dims) = &target_kind {
if let ValueKind::Matrix(source_element_kind, _) = source_value.kind() {
if target_dims.is_empty()
&& source_element_kind == *target_element_kind
&& !matches!(source_value, Value::MatrixValue(_))
{
return Ok(Box::new(ConvertMatPassthrough { out: Ref::new(source_value.clone()) }));
}
}
}
let shape = source_value.shape();
paste::paste! {
match (source_value.clone(), target_kind.clone()) {
$(
#[cfg(all(feature = "matrix", feature = $src_string))]
(Value::[<Matrix $src:camel>](v), ValueKind::Matrix(target_kind, dims)) if matches!(target_kind.as_ref(), ValueKind::Any) => {
if dims.is_empty() {
create_convert_mat_to_mat::<$src, $src>(v, &shape)
} else if ((shape[0] == dims[0]) && (shape[1] == dims[1])) {
create_convert_mat_to_mat::<$src, $src>(v, &dims)
} else if shape[0] * shape[1] == dims[0] * dims[1] {
create_reshape_mat_to_mat::<$src, $src>(v, &dims)
} else {
Err(MechError::new(UnsupportedConversionError{from: source_value.kind(), to: target_kind.as_ref().clone()}, None).with_compiler_loc())
}
}
$(
#[cfg(all(feature = "matrix", feature = $src_string, feature = $dst_string))]
(Value::[<Matrix $src:camel>](v), ValueKind::Matrix(target_kind, dims)) if matches!(target_kind.as_ref(), ValueKind::[<$dst:camel>]) => {
if dims.is_empty() {
create_convert_mat_to_mat::<$src, $dst>(v, &shape)
} else if ((shape[0] == dims[0]) && (shape[1] == dims[1])) {
create_convert_mat_to_mat::<$src, $dst>(v, &dims)
} else if shape[0] * shape[1] == dims[0] * dims[1] {
create_reshape_mat_to_mat::<$src, $dst>(v, &dims)
} else {
Err(MechError::new(UnsupportedConversionError{from: source_value.kind(), to: target_kind.as_ref().clone()}, None).with_compiler_loc())
}
}
)+
)+
_ => Err(MechError::new(UnsupportedConversionError{from: source_value.kind(), to: target_kind.clone()}, None).with_compiler_loc()),
}
}
}
};
}
fn matrix_value_to_concrete_matrix(
converted: Vec<Value>,
target_element_kind: &ValueKind,
output_shape: &[usize],
) -> MResult<Value> {
macro_rules! cast_matrix_values {
($values:expr, $shape:expr, $scalar_variant:ident, $scalar_ty:ty, $matrix_variant:ident) => {{
let values = $values
.into_iter()
.map(|value| match value {
Value::$scalar_variant(v) => Ok((*v.borrow()).clone()),
other => Err(MechError::new(
UnsupportedConversionError {
from: other.kind(),
to: target_element_kind.clone(),
},
None,
)
.with_compiler_loc()),
})
.collect::<MResult<Vec<$scalar_ty>>>()?;
Ok(Value::$matrix_variant(Matrix::from_vec(
values, $shape[0], $shape[1],
)))
}};
}
match target_element_kind {
#[cfg(feature = "bool")]
ValueKind::Bool => cast_matrix_values!(converted, output_shape, Bool, bool, MatrixBool),
#[cfg(feature = "u8")]
ValueKind::U8 => cast_matrix_values!(converted, output_shape, U8, u8, MatrixU8),
#[cfg(feature = "u16")]
ValueKind::U16 => cast_matrix_values!(converted, output_shape, U16, u16, MatrixU16),
#[cfg(feature = "u32")]
ValueKind::U32 => cast_matrix_values!(converted, output_shape, U32, u32, MatrixU32),
#[cfg(feature = "u64")]
ValueKind::U64 => cast_matrix_values!(converted, output_shape, U64, u64, MatrixU64),
#[cfg(feature = "u128")]
ValueKind::U128 => cast_matrix_values!(converted, output_shape, U128, u128, MatrixU128),
#[cfg(feature = "i8")]
ValueKind::I8 => cast_matrix_values!(converted, output_shape, I8, i8, MatrixI8),
#[cfg(feature = "i16")]
ValueKind::I16 => cast_matrix_values!(converted, output_shape, I16, i16, MatrixI16),
#[cfg(feature = "i32")]
ValueKind::I32 => cast_matrix_values!(converted, output_shape, I32, i32, MatrixI32),
#[cfg(feature = "i64")]
ValueKind::I64 => cast_matrix_values!(converted, output_shape, I64, i64, MatrixI64),
#[cfg(feature = "i128")]
ValueKind::I128 => cast_matrix_values!(converted, output_shape, I128, i128, MatrixI128),
#[cfg(feature = "f32")]
ValueKind::F32 => cast_matrix_values!(converted, output_shape, F32, f32, MatrixF32),
#[cfg(feature = "f64")]
ValueKind::F64 => cast_matrix_values!(converted, output_shape, F64, f64, MatrixF64),
#[cfg(feature = "string")]
ValueKind::String => {
cast_matrix_values!(converted, output_shape, String, String, MatrixString)
}
#[cfg(feature = "rational")]
ValueKind::R64 => cast_matrix_values!(converted, output_shape, R64, R64, MatrixR64),
#[cfg(feature = "complex")]
ValueKind::C64 => cast_matrix_values!(converted, output_shape, C64, C64, MatrixC64),
_ => Ok(Value::MatrixValue(Matrix::from_vec(
converted,
output_shape[0],
output_shape[1],
))),
}
}
#[cfg(not(target_arch = "wasm32"))]
impl_conversion_mat_to_mat_fxn! {
f64, "f64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128", R64, "rational"];
f32, "f32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128", R64, "rational"];
u8, "u8" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
u16, "u16" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
u32, "u32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
u64, "u64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
u128,"u128"=> [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
i8, "i8" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
i16, "i16" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
i32, "i32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
i64, "i64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
i128,"i128"=> [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
bool, "bool" => [bool, "bool", String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", u128, "u128", i8, "i8", i16, "i16", i32, "i32", i64, "i64", i128, "i128"];
String, "string" => [String, "string"];
R64, "rational" => [String, "string"];
C64, "complex" => [String, "string"];
}
#[cfg(target_arch = "wasm32")]
impl_conversion_mat_to_mat_fxn! {
f64, "f64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64", R64, "rational"];
f32, "f32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64", R64, "rational"];
u8, "u8" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
u16, "u16" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
u32, "u32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
u64, "u64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
i8, "i8" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
i16, "i16" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
i32, "i32" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
i64, "i64" => [String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
bool, "bool" => [bool, "bool", String, "string", f64, "f64", f32, "f32", u8, "u8", u16, "u16", u32, "u32", u64, "u64", i8, "i8", i16, "i16", i32, "i32", i64, "i64"];
String, "string" => [String, "string"];
R64, "rational" => [String, "string"];
C64, "complex" => [String, "string"];
}
pub struct ConvertMatToMat {}
impl NativeFunctionCompiler for ConvertMatToMat {
fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
if arguments.len() != 2 {
return Err(MechError::new(
IncorrectNumberOfArguments {
expected: 2,
found: arguments.len(),
},
None,
)
.with_compiler_loc());
}
let source_value = arguments[0].clone();
let target_kind = arguments[1].kind();
match impl_conversion_mat_to_mat_fxn(source_value.clone(), target_kind.clone()) {
Ok(fxn) => Ok(fxn),
Err(err) => match source_value {
Value::MutableReference(rhs) => {
impl_conversion_mat_to_mat_fxn(rhs.borrow().clone(), target_kind.clone())
.or(Err(err))
}
_ => Err(err),
},
}
}
}
#[derive(Debug, Clone)]
pub struct ReshapeError {
pub requested: (usize, usize),
pub original: (usize, usize),
}
impl MechErrorKind for ReshapeError {
fn name(&self) -> &str {
"ReshapeError"
}
fn message(&self) -> String {
format!(
"Cannot reshape matrix of shape {:?} into {:?}",
self.original, self.requested
)
}
}