types: mat: hack in a way to implement a 3-variant material

This commit is contained in:
2022-07-22 01:46:07 -07:00
parent a8b6000104
commit 50ae6d4c34
3 changed files with 54 additions and 35 deletions

View File

@@ -168,6 +168,13 @@ impl<L> Enum<(), L> {
}
}
impl<D, L> Enum<D, L> {
/// use with care. long term, this probably shouldn't stay public.
pub fn from_components(discr: D, list: L) -> Self {
Self(discr, list)
}
}
pub trait EnumRequirements {
type NumVariants: Peano;
fn decode_discr(&self) -> Discr<Self::NumVariants>;

View File

@@ -128,6 +128,10 @@ pub trait IntoList {
}
pub type List<Args> = <Args as IntoList>::List;
pub type List1<E0> = Node<E0, Null>;
pub type List2<E0, E1> = Node<E0, List1<E1>>;
pub type List3<E0, E1, E2> = Node<E0, List2<E1, E2>>;
pub type List4<E0, E1, E2, E3> = Node<E0, List3<E1, E2, E3>>;
impl<H> Meta for Node<H, Null> {
type Length = P1;

View File

@@ -1,6 +1,6 @@
use crate::compound::enumerated::{Discr, DiscriminantCodable, Enum, EnumRequirements, InternallyDiscriminated, VariantHandler};
use crate::compound::list::{IntoList as _, List};
use crate::compound::peano::{Peano, P2};
use crate::compound::list::{Indexable, IntoList, List, List2, List3};
use crate::compound::peano::{Peano, P0, P1, P2, P3};
use crate::real::Real;
use crate::vec::Vec3;
@@ -27,40 +27,31 @@ pub trait Material<R: Real>: Sized {
}
}
/// a material which can take on 1 of N types.
/// it's assumed that the first type in the material list is capable of storing the discriminant
/// (i.e. that it implements DiscriminantCodable).
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "fmt", derive(Debug))]
#[derive(Copy, Clone, Default, PartialEq)]
pub struct DiscrMat2<M0, M1>(InternallyDiscriminated<(M0, M1)>);
#[derive(Clone, Default, PartialEq)]
pub struct DiscrMat<Mats>(Enum<(), Mats>);
pub type DiscrMat2<M0, M1> = DiscrMat<List2<M0, M1>>;
pub type DiscrMat3<M0, M1, M2> = DiscrMat<List3<M0, M1, M2>>;
struct D0<T>(T);
struct D1<T>(T);
impl<M0, M1> DiscrMat2<M0, M1> {
fn new_from_fields(m0: M0, m1: M1) -> Self {
Self(Enum::internally_discriminated((m0, m1)))
impl<Mats> DiscrMat<Mats> {
fn new_from_fields(mats: Mats) -> Self {
Self(Enum::from_components((), mats))
}
}
impl<M0: DiscriminantCodable<P2>, M1: Default> DiscrMat2<M0, M1> {
pub fn new0(m: M0) -> Self {
D0(m).into()
}
pub fn new1(m: M1) -> Self {
D1(m).into()
}
}
impl<M0, M1: Default> From<D0<M0>> for DiscrMat2<M0, M1> {
fn from(m0: D0<M0>) -> Self {
let m0 = m0.0;
Self::new_from_fields(m0, Default::default())
}
}
impl<M0: DiscriminantCodable<P2>, M1> From<D1<M1>> for DiscrMat2<M0, M1> {
fn from(m1: D1<M1>) -> Self {
let m1 = m1.0;
Self::new_from_fields(M0::encode_discr(Discr::new(1)), m1)
impl<Mats: Default> DiscrMat<Mats> {
fn new<P: Peano>(m: Mats::Element) -> Self
where
Mats: Indexable<P>,
Enum<(), Mats>: EnumRequirements,
{
let mut me = Self::default();
me.0.set::<P>(m);
me
}
}
@@ -81,7 +72,24 @@ impl<R: Real, P: Peano, T: Material<R>> VariantHandler<P, T, Vec3<R>> for MoveBV
}
}
impl<R: Real, M0: DiscriminantCodable<P2> + Material<R> + Copy, M1: Material<R> + Copy> Material<R> for DiscrMat2<M0, M1>
impl<R: Real, M0, M1> Material<R> for DiscrMat2<M0, M1>
where
M0: DiscriminantCodable<P2> + Material<R> + Copy,
M1: Material<R> + Copy,
{
fn conductivity(&self) -> Vec3<R> {
self.0.dispatch(ConductivityDispatcher)
}
fn move_b_vec(&self, m: Vec3<R>, target_b: Vec3<R>) -> Vec3<R> {
self.0.dispatch(MoveBVecDispatcher { m, target_b })
}
}
impl<R: Real, M0, M1, M2> Material<R> for DiscrMat3<M0, M1, M2>
where
M0: DiscriminantCodable<P3> + Material<R> + Copy,
M1: Material<R> + Copy,
M2: Material<R> + Copy,
{
fn conductivity(&self) -> Vec3<R> {
self.0.dispatch(ConductivityDispatcher)
@@ -97,12 +105,12 @@ pub type IsoConductorOr<R, M1> = DiscrMat2<IsomorphicConductor<R>, M1>;
// IsomorphicConductor itself
impl<R: Real> From<Ferroxcube3R1MH> for IsoConductorOr<R, Ferroxcube3R1MH> {
fn from(mat: Ferroxcube3R1MH) -> Self {
IsoConductorOr::new1(mat)
IsoConductorOr::new::<P1>(mat)
}
}
impl<R: Real> From<IsomorphicConductor<R>> for IsoConductorOr<R, Ferroxcube3R1MH> {
fn from(mat: IsomorphicConductor<R>) -> Self {
IsoConductorOr::new0(mat)
IsoConductorOr::new::<P0>(mat)
}
}
@@ -124,10 +132,10 @@ mod test {
fn iso_conductor_or_aniso() {
type I = IsoConductorOr<R32, AnisomorphicConductor<R32>>;
let c = I::new0(IsomorphicConductor::new(22f32.cast()));
let c = I::new::<P0>(IsomorphicConductor::new(22f32.cast()));
assert!(c.conductivity() == Vec3::uniform(22.0).cast());
let c = I::new1(AnisomorphicConductor::new(
let c = I::new::<P1>(AnisomorphicConductor::new(
Vec3::new(2.0, 3.0, 4.0).cast()
));