use furiosa_mapping::*;
use furiosa_opt_macro::primitive;
use furiosa_opt_lower::{CommitInput, config_commit};
use crate::backend::Backend;
use crate::context::*;
use crate::engine::CanApplyCommit;
use crate::scalar::*;
use crate::tensor::memory::{DmTensor, DmTensorViewMut};
use crate::tensor::tu::TuTensor;
impl<'l, const T: Tu, P: CanApplyCommit, D: Scalar, Chip: M, Cluster: M, Slice: M, Time: M, Packet: M, B: Backend>
TuTensor<'l, T, P, D, Chip, Cluster, Slice, Time, Packet, B>
{
#[primitive(TuTensor::commit)]
pub fn commit<Element: M>(self) -> DmTensor<D, Chip, Cluster, Slice, Element, B> {
verify_commit::<D, Time, Packet, Element>();
DmTensor::from_parts(self.inner.transpose(false), None)
}
#[primitive(TuTensor::commit_view)]
pub fn commit_view<Element: M>(self, mut dst: DmTensorViewMut<'l, D, Chip, Cluster, Slice, Element, B>) {
verify_commit::<D, Time, Packet, Element>();
dst.inner.transpose(self.inner.view(), false);
}
}
pub(crate) fn verify_commit<D: Scalar, InTime: M, InPacket: M, Element: M>() {
let _ = config_commit(CommitInput {
in_time: InTime::to_value(),
in_packet: InPacket::to_value(),
element: Element::to_value(),
element_bits: D::BITS,
})
.unwrap_or_else(|e| panic!("{e}"));
}
#[cfg(test)]
mod tests {
use super::*;
use furiosa_opt_lower::CommitError;
mod commit_valid {
use super::*;
axes![N = 8, A = 4, B = 3, C = 4];
#[test]
fn full_trim_then_commit() {
verify_commit::<i8, m![A, B, C], m![N], m![A, B, C, N]>();
}
#[test]
fn partial_trim_then_commit() {
verify_commit::<i8, m![A], m![N # 16], m![A, N # 16]>();
}
#[test]
fn time_transpose() {
verify_commit::<i8, m![A # 32, B], m![N], m![B, A # 32, N]>();
}
#[test]
fn interleaved_time_padding_overlaps_into_dm_padding() {
verify_commit::<i8, m![1 # 2, A, 1 # 2], m![N], m![A, 1 # 3, N]>();
}
}
mod commit_invalid {
use super::*;
use furiosa_mapping::M as _;
axes![M = 4, N = 8, X = 8, Y = 4, A = 4, B = 3];
#[test]
fn illegal_packet_size() {
assert_eq!(
config_commit(CommitInput {
in_time: <m![M]>::to_value(),
in_packet: <m![B]>::to_value(),
element: <m![M, B]>::to_value(),
element_bits: <i8 as Scalar>::BITS,
}),
Err(CommitError::IllegalPacketBytes { bytes: B::SIZE })
);
}
#[test]
fn packet_mismatch() {
assert!(matches!(
config_commit(CommitInput {
in_time: <m![M]>::to_value(),
in_packet: <m![N # 32]>::to_value(),
element: <m![M, X]>::to_value(),
element_bits: <i8 as Scalar>::BITS,
}),
Err(CommitError::PacketNotInnermost { .. })
));
}
#[test]
fn time_term_mismatch() {
assert!(matches!(
config_commit(CommitInput {
in_time: <m![M]>::to_value(),
in_packet: <m![N # 32]>::to_value(),
element: <m![Y, N # 32]>::to_value(),
element_bits: <i8 as Scalar>::BITS,
}),
Err(CommitError::Unwritable { .. })
));
}
#[test]
fn no_affine_plan() {
assert!(matches!(
config_commit(CommitInput {
in_time: <m![A, 1 # 5]>::to_value(),
in_packet: <m![N]>::to_value(),
element: <m![A, 1 # 2, N]>::to_value(),
element_bits: <i8 as Scalar>::BITS,
}),
Err(CommitError::Unwritable { .. })
));
}
}
}