Skip to main content

bevy_math/curve/
cores.rs

1//! Core data structures to be used internally in Curve implementations, encapsulating storage
2//! and access patterns for reuse.
3//!
4//! The `Core` types here expose their fields publicly so that it is easier to manipulate and
5//! extend them, but in doing so, you must maintain the invariants of those fields yourself. The
6//! provided methods all maintain the invariants, so this is only a concern if you manually mutate
7//! the fields.
8
9use crate::ops;
10
11use super::interval::Interval;
12use core::fmt::Debug;
13use thiserror::Error;
14
15#[cfg(feature = "alloc")]
16use {alloc::vec::Vec, itertools::Itertools};
17
18#[cfg(feature = "bevy_reflect")]
19use bevy_reflect::Reflect;
20
21/// This type expresses the relationship of a value to a fixed collection of values. It is a kind
22/// of summary used intermediately by sampling operations.
23#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for InterpolationDatum<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            InterpolationDatum::Exact(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Exact",
                    &__self_0),
            InterpolationDatum::LeftTail(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "LeftTail", &__self_0),
            InterpolationDatum::RightTail(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "RightTail", &__self_0),
            InterpolationDatum::Between(__self_0, __self_1, __self_2) =>
                ::core::fmt::Formatter::debug_tuple_field3_finish(f,
                    "Between", __self_0, __self_1, &__self_2),
        }
    }
}Debug, #[automatically_derived]
impl<T: ::core::marker::Copy> ::core::marker::Copy for InterpolationDatum<T> {
}Copy, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for InterpolationDatum<T> {
    #[inline]
    fn clone(&self) -> InterpolationDatum<T> {
        match self {
            InterpolationDatum::Exact(__self_0) =>
                InterpolationDatum::Exact(::core::clone::Clone::clone(__self_0)),
            InterpolationDatum::LeftTail(__self_0) =>
                InterpolationDatum::LeftTail(::core::clone::Clone::clone(__self_0)),
            InterpolationDatum::RightTail(__self_0) =>
                InterpolationDatum::RightTail(::core::clone::Clone::clone(__self_0)),
            InterpolationDatum::Between(__self_0, __self_1, __self_2) =>
                InterpolationDatum::Between(::core::clone::Clone::clone(__self_0),
                    ::core::clone::Clone::clone(__self_1),
                    ::core::clone::Clone::clone(__self_2)),
        }
    }
}Clone, #[automatically_derived]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
    InterpolationDatum<T> {
    #[inline]
    fn eq(&self, other: &InterpolationDatum<T>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (InterpolationDatum::Exact(__self_0),
                    InterpolationDatum::Exact(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (InterpolationDatum::LeftTail(__self_0),
                    InterpolationDatum::LeftTail(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (InterpolationDatum::RightTail(__self_0),
                    InterpolationDatum::RightTail(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (InterpolationDatum::Between(__self_0, __self_1, __self_2),
                    InterpolationDatum::Between(__arg1_0, __arg1_1, __arg1_2))
                    =>
                    __self_2 == __arg1_2 && __self_0 == __arg1_0 &&
                        __self_1 == __arg1_1,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
24#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<T> _serde::Serialize for InterpolationDatum<T> where
            T: _serde::Serialize {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                match *self {
                    InterpolationDatum::Exact(ref __field0) =>
                        _serde::Serializer::serialize_newtype_variant(__serializer,
                            "InterpolationDatum", 0u32, "Exact", __field0),
                    InterpolationDatum::LeftTail(ref __field0) =>
                        _serde::Serializer::serialize_newtype_variant(__serializer,
                            "InterpolationDatum", 1u32, "LeftTail", __field0),
                    InterpolationDatum::RightTail(ref __field0) =>
                        _serde::Serializer::serialize_newtype_variant(__serializer,
                            "InterpolationDatum", 2u32, "RightTail", __field0),
                    InterpolationDatum::Between(ref __field0, ref __field1,
                        ref __field2) => {
                        let mut __serde_state =
                            _serde::Serializer::serialize_tuple_variant(__serializer,
                                    "InterpolationDatum", 3u32, "Between", 0 + 1 + 1 + 1)?;
                        _serde::ser::SerializeTupleVariant::serialize_field(&mut __serde_state,
                                __field0)?;
                        _serde::ser::SerializeTupleVariant::serialize_field(&mut __serde_state,
                                __field1)?;
                        _serde::ser::SerializeTupleVariant::serialize_field(&mut __serde_state,
                                __field2)?;
                        _serde::ser::SerializeTupleVariant::end(__serde_state)
                    }
                }
            }
        }
    };serde::Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de, T> _serde::Deserialize<'de> for InterpolationDatum<T> where
            T: _serde::Deserialize<'de> {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, __field2, __field3, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "variant identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            2u64 => _serde::__private228::Ok(__Field::__field2),
                            3u64 => _serde::__private228::Ok(__Field::__field3),
                            _ =>
                                _serde::__private228::Err(_serde::de::Error::invalid_value(_serde::de::Unexpected::Unsigned(__value),
                                        &"variant index 0 <= i < 4")),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "Exact" => _serde::__private228::Ok(__Field::__field0),
                            "LeftTail" => _serde::__private228::Ok(__Field::__field1),
                            "RightTail" => _serde::__private228::Ok(__Field::__field2),
                            "Between" => _serde::__private228::Ok(__Field::__field3),
                            _ => {
                                _serde::__private228::Err(_serde::de::Error::unknown_variant(__value,
                                        VARIANTS))
                            }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"Exact" => _serde::__private228::Ok(__Field::__field0),
                            b"LeftTail" => _serde::__private228::Ok(__Field::__field1),
                            b"RightTail" => _serde::__private228::Ok(__Field::__field2),
                            b"Between" => _serde::__private228::Ok(__Field::__field3),
                            _ => {
                                let __value =
                                    &_serde::__private228::from_utf8_lossy(__value);
                                _serde::__private228::Err(_serde::de::Error::unknown_variant(__value,
                                        VARIANTS))
                            }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de, T> where T: _serde::Deserialize<'de> {
                    marker: _serde::__private228::PhantomData<InterpolationDatum<T>>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
                    where T: _serde::Deserialize<'de> {
                    type Value = InterpolationDatum<T>;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "enum InterpolationDatum")
                    }
                    fn visit_enum<__A>(self, __data: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::EnumAccess<'de> {
                        match _serde::de::EnumAccess::variant(__data)? {
                            (__Field::__field0, __variant) =>
                                _serde::__private228::Result::map(_serde::de::VariantAccess::newtype_variant::<T>(__variant),
                                    InterpolationDatum::Exact),
                            (__Field::__field1, __variant) =>
                                _serde::__private228::Result::map(_serde::de::VariantAccess::newtype_variant::<T>(__variant),
                                    InterpolationDatum::LeftTail),
                            (__Field::__field2, __variant) =>
                                _serde::__private228::Result::map(_serde::de::VariantAccess::newtype_variant::<T>(__variant),
                                    InterpolationDatum::RightTail),
                            (__Field::__field3, __variant) => {
                                #[doc(hidden)]
                                struct __Visitor<'de, T> where T: _serde::Deserialize<'de> {
                                    marker: _serde::__private228::PhantomData<InterpolationDatum<T>>,
                                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                                }
                                #[automatically_derived]
                                impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
                                    where T: _serde::Deserialize<'de> {
                                    type Value = InterpolationDatum<T>;
                                    fn expecting(&self,
                                        __formatter: &mut _serde::__private228::Formatter)
                                        -> _serde::__private228::fmt::Result {
                                        _serde::__private228::Formatter::write_str(__formatter,
                                            "tuple variant InterpolationDatum::Between")
                                    }
                                    #[inline]
                                    fn visit_seq<__A>(self, mut __seq: __A)
                                        -> _serde::__private228::Result<Self::Value, __A::Error>
                                        where __A: _serde::de::SeqAccess<'de> {
                                        let __field0 =
                                            match _serde::de::SeqAccess::next_element::<T>(&mut __seq)?
                                                {
                                                _serde::__private228::Some(__value) => __value,
                                                _serde::__private228::None =>
                                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
                                                                &"tuple variant InterpolationDatum::Between with 3 elements")),
                                            };
                                        let __field1 =
                                            match _serde::de::SeqAccess::next_element::<T>(&mut __seq)?
                                                {
                                                _serde::__private228::Some(__value) => __value,
                                                _serde::__private228::None =>
                                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
                                                                &"tuple variant InterpolationDatum::Between with 3 elements")),
                                            };
                                        let __field2 =
                                            match _serde::de::SeqAccess::next_element::<f32>(&mut __seq)?
                                                {
                                                _serde::__private228::Some(__value) => __value,
                                                _serde::__private228::None =>
                                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(2usize,
                                                                &"tuple variant InterpolationDatum::Between with 3 elements")),
                                            };
                                        _serde::__private228::Ok(InterpolationDatum::Between(__field0,
                                                __field1, __field2))
                                    }
                                }
                                _serde::de::VariantAccess::tuple_variant(__variant, 3usize,
                                    __Visitor {
                                        marker: _serde::__private228::PhantomData::<InterpolationDatum<T>>,
                                        lifetime: _serde::__private228::PhantomData,
                                    })
                            }
                        }
                    }
                }
                #[doc(hidden)]
                const VARIANTS: &'static [&'static str] =
                    &["Exact", "LeftTail", "RightTail", "Between"];
                _serde::Deserializer::deserialize_enum(__deserializer,
                    "InterpolationDatum", VARIANTS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<InterpolationDatum<T>>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };serde::Deserialize))]
25#[cfg_attr(feature = "bevy_reflect", derive(const _: () =
    {
        impl<T> bevy_reflect::GetTypeRegistration for InterpolationDatum<T>
            where InterpolationDatum<T>: ::core::any::Any +
            ::core::marker::Send + ::core::marker::Sync,
            T: bevy_reflect::TypePath, T: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <T as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <f32 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl<T> bevy_reflect::Typed for InterpolationDatum<T> where
            InterpolationDatum<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            bevy_reflect::TypeInfo::Enum(bevy_reflect::enums::EnumInfo::new::<Self>(&[bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Exact",
                                                            &[bevy_reflect::UnnamedField::new::<T>(0usize)])),
                                                    bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("LeftTail",
                                                            &[bevy_reflect::UnnamedField::new::<T>(0usize)])),
                                                    bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("RightTail",
                                                            &[bevy_reflect::UnnamedField::new::<T>(0usize)])),
                                                    bevy_reflect::enums::VariantInfo::Tuple(bevy_reflect::enums::TupleVariantInfo::new("Between",
                                                            &[bevy_reflect::UnnamedField::new::<T>(0usize),
                                                                        bevy_reflect::UnnamedField::new::<T>(1usize),
                                                                        bevy_reflect::UnnamedField::new::<f32>(2usize)]))]).with_generics(bevy_reflect::Generics::from_iter([bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<T>(bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("T")))])))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<T> bevy_reflect::TypePath for InterpolationDatum<T> where
            InterpolationDatum<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_math::curve::cores::InterpolationDatum<"),
                                    <T as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("InterpolationDatum<"),
                                    <T as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("InterpolationDatum")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::curve::cores".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::curve::cores")
            }
        }
        impl<T> bevy_reflect::Reflect for InterpolationDatum<T> where
            InterpolationDatum<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<T> bevy_reflect::enums::Enum for InterpolationDatum<T> where
            InterpolationDatum<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn field(&self, __name_param: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at(&self, __index_param: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match self {
                    InterpolationDatum::Exact { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::LeftTail { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::RightTail { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::Between { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::Between { 1: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::Between { 2: __value, .. } if
                        __index_param == 2usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, __name_param: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self { _ => ::core::option::Option::None, }
            }
            fn field_at_mut(&mut self, __index_param: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match self {
                    InterpolationDatum::Exact { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::LeftTail { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::RightTail { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::Between { 0: __value, .. } if
                        __index_param == 0usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::Between { 1: __value, .. } if
                        __index_param == 1usize =>
                        ::core::option::Option::Some(__value),
                    InterpolationDatum::Between { 2: __value, .. } if
                        __index_param == 2usize =>
                        ::core::option::Option::Some(__value),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of(&self, __name_param: &str)
                -> ::core::option::Option<usize> {
                match self { _ => ::core::option::Option::None, }
            }
            fn name_at(&self, __index_param: usize)
                -> ::core::option::Option<&str> {
                match self { _ => ::core::option::Option::None, }
            }
            fn iter_fields(&self) -> bevy_reflect::enums::VariantFieldIter {
                bevy_reflect::enums::VariantFieldIter::new(self)
            }
            #[inline]
            fn field_len(&self) -> usize {
                match self {
                    InterpolationDatum::Exact { .. } => 1usize,
                    InterpolationDatum::LeftTail { .. } => 1usize,
                    InterpolationDatum::RightTail { .. } => 1usize,
                    InterpolationDatum::Between { .. } => 3usize,
                    _ => 0,
                }
            }
            #[inline]
            fn variant_name(&self) -> &str {
                match self {
                    InterpolationDatum::Exact { .. } => "Exact",
                    InterpolationDatum::LeftTail { .. } => "LeftTail",
                    InterpolationDatum::RightTail { .. } => "RightTail",
                    InterpolationDatum::Between { .. } => "Between",
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_index(&self) -> usize {
                match self {
                    InterpolationDatum::Exact { .. } => 0usize,
                    InterpolationDatum::LeftTail { .. } => 1usize,
                    InterpolationDatum::RightTail { .. } => 2usize,
                    InterpolationDatum::Between { .. } => 3usize,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            #[inline]
            fn variant_type(&self) -> bevy_reflect::enums::VariantType {
                match self {
                    InterpolationDatum::Exact { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    InterpolationDatum::LeftTail { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    InterpolationDatum::RightTail { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    InterpolationDatum::Between { .. } =>
                        bevy_reflect::enums::VariantType::Tuple,
                    _ =>
                        ::core::panicking::panic("internal error: entered unreachable code"),
                }
            }
            fn to_dynamic_enum(&self) -> bevy_reflect::enums::DynamicEnum {
                bevy_reflect::enums::DynamicEnum::from_ref::<Self>(self)
            }
        }
        impl<T> bevy_reflect::PartialReflect for InterpolationDatum<T> where
            InterpolationDatum<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self,
                __value_param: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Enum(__value_param) =
                        bevy_reflect::PartialReflect::reflect_ref(__value_param) {
                    if bevy_reflect::enums::Enum::variant_name(self) ==
                            bevy_reflect::enums::Enum::variant_name(__value_param) {
                        match bevy_reflect::enums::Enum::variant_type(__value_param)
                            {
                            bevy_reflect::enums::VariantType::Struct => {
                                for field in
                                    bevy_reflect::enums::Enum::iter_fields(__value_param) {
                                    let name = field.name().unwrap();
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_mut(self, name) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            bevy_reflect::enums::VariantType::Tuple => {
                                for (index, field) in
                                    ::core::iter::Iterator::enumerate(bevy_reflect::enums::Enum::iter_fields(__value_param))
                                    {
                                    if let ::core::option::Option::Some(v) =
                                            bevy_reflect::enums::Enum::field_at_mut(self, index) {
                                        bevy_reflect::PartialReflect::try_apply(v, field.value())?;
                                    }
                                }
                            }
                            _ => {}
                        }
                    } else {
                        match bevy_reflect::enums::Enum::variant_name(__value_param)
                            {
                            "Exact" => {
                                *self =
                                    InterpolationDatum::Exact {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Exact"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <T as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<T as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "LeftTail" => {
                                *self =
                                    InterpolationDatum::LeftTail {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("LeftTail"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <T as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<T as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "RightTail" => {
                                *self =
                                    InterpolationDatum::RightTail {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("RightTail"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <T as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<T as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            "Between" => {
                                *self =
                                    InterpolationDatum::Between {
                                        0: {
                                            let __0 = __value_param.field_at(0usize);
                                            let __0 =
                                                __0.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Between"),
                                                            field_name: ::core::convert::Into::into(".0"),
                                                        })?;
                                            <T as
                                                            bevy_reflect::FromReflect>::from_reflect(__0).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__0)),
                                                        to_type: ::core::convert::Into::into(<T as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                        1: {
                                            let __1 = __value_param.field_at(1usize);
                                            let __1 =
                                                __1.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Between"),
                                                            field_name: ::core::convert::Into::into(".1"),
                                                        })?;
                                            <T as
                                                            bevy_reflect::FromReflect>::from_reflect(__1).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__1)),
                                                        to_type: ::core::convert::Into::into(<T as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                        2: {
                                            let __2 = __value_param.field_at(2usize);
                                            let __2 =
                                                __2.ok_or(bevy_reflect::ApplyError::MissingEnumField {
                                                            variant_name: ::core::convert::Into::into("Between"),
                                                            field_name: ::core::convert::Into::into(".2"),
                                                        })?;
                                            <f32 as
                                                            bevy_reflect::FromReflect>::from_reflect(__2).ok_or(bevy_reflect::ApplyError::MismatchedTypes {
                                                        from_type: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(__2)),
                                                        to_type: ::core::convert::Into::into(<f32 as
                                                                    bevy_reflect::TypePath>::type_path()),
                                                    })?
                                        },
                                    }
                            }
                            name => {
                                return ::core::result::Result::Err(bevy_reflect::ApplyError::UnknownVariant {
                                            enum_name: ::core::convert::Into::into(bevy_reflect::DynamicTypePath::reflect_type_path(self)),
                                            variant_name: ::core::convert::Into::into(name),
                                        });
                            }
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(__value_param),
                                to_kind: bevy_reflect::ReflectKind::Enum,
                            });
                }
                ::core::result::Result::Ok(())
            }
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Enum
            }
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Enum(self)
            }
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Enum(self)
            }
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Enum(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_hash(&self) -> ::core::option::Option<u64> {
                (bevy_reflect::enums::enum_hash)(self)
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::enums::enum_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::enums::enum_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                let this = self;
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(match this
                            {
                            InterpolationDatum::Exact { 0: __0 } =>
                                InterpolationDatum::Exact {
                                    0: <T as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                            InterpolationDatum::LeftTail { 0: __0 } =>
                                InterpolationDatum::LeftTail {
                                    0: <T as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                            InterpolationDatum::RightTail { 0: __0 } =>
                                InterpolationDatum::RightTail {
                                    0: <T as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                },
                            InterpolationDatum::Between { 0: __0, 1: __1, 2: __2 } =>
                                InterpolationDatum::Between {
                                    0: <T as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__0)?,
                                    1: <T as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__1)?,
                                    2: <f32 as
                                                bevy_reflect::PartialReflect>::reflect_clone_and_take(__2)?,
                                },
                        }))
            }
        }
        impl<T> bevy_reflect::FromReflect for InterpolationDatum<T> where
            InterpolationDatum<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            T: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn from_reflect(__param0: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Enum(__param0) =
                        bevy_reflect::PartialReflect::reflect_ref(__param0) {
                    match bevy_reflect::enums::Enum::variant_name(__param0) {
                        "Exact" =>
                            ::core::option::Option::Some(InterpolationDatum::Exact {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <T as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "LeftTail" =>
                            ::core::option::Option::Some(InterpolationDatum::LeftTail {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <T as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "RightTail" =>
                            ::core::option::Option::Some(InterpolationDatum::RightTail {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <T as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                }),
                        "Between" =>
                            ::core::option::Option::Some(InterpolationDatum::Between {
                                    0: {
                                        let __0 = __param0.field_at(0usize);
                                        let __0 = __0?;
                                        <T as bevy_reflect::FromReflect>::from_reflect(__0)?
                                    },
                                    1: {
                                        let __1 = __param0.field_at(1usize);
                                        let __1 = __1?;
                                        <T as bevy_reflect::FromReflect>::from_reflect(__1)?
                                    },
                                    2: {
                                        let __2 = __param0.field_at(2usize);
                                        let __2 = __2?;
                                        <f32 as bevy_reflect::FromReflect>::from_reflect(__2)?
                                    },
                                }),
                        name => ::core::option::Option::None,
                    }
                } else { ::core::option::Option::None }
            }
        }
    };Reflect))]
26pub enum InterpolationDatum<T> {
27    /// This value lies exactly on a value in the family.
28    Exact(T),
29
30    /// This value is off the left tail of the family; the inner value is the family's leftmost.
31    LeftTail(T),
32
33    /// This value is off the right tail of the family; the inner value is the family's rightmost.
34    RightTail(T),
35
36    /// This value lies on the interior, in between two points, with a third parameter expressing
37    /// the interpolation factor between the two.
38    Between(T, T, f32),
39}
40
41impl<T> InterpolationDatum<T> {
42    /// Map all values using a given function `f`, leaving the interpolation parameters in any
43    /// [`Between`] variants unchanged.
44    ///
45    /// [`Between`]: `InterpolationDatum::Between`
46    #[must_use]
47    pub fn map<S>(self, f: impl Fn(T) -> S) -> InterpolationDatum<S> {
48        match self {
49            InterpolationDatum::Exact(v) => InterpolationDatum::Exact(f(v)),
50            InterpolationDatum::LeftTail(v) => InterpolationDatum::LeftTail(f(v)),
51            InterpolationDatum::RightTail(v) => InterpolationDatum::RightTail(f(v)),
52            InterpolationDatum::Between(u, v, s) => InterpolationDatum::Between(f(u), f(v), s),
53        }
54    }
55}
56
57/// The data core of a curve derived from evenly-spaced samples. The intention is to use this
58/// in addition to explicit or inferred interpolation information in user-space in order to
59/// implement curves using [`domain`] and [`sample_with`].
60///
61/// The internals are made transparent to give curve authors freedom, but [the provided constructor]
62/// enforces the required invariants, and the methods maintain those invariants.
63///
64/// [the provided constructor]: EvenCore::new
65/// [`domain`]: EvenCore::domain
66/// [`sample_with`]: EvenCore::sample_with
67///
68/// # Example
69/// ```rust
70/// # use bevy_math::curve::*;
71/// # use bevy_math::curve::cores::*;
72/// // Let's make a curve that interpolates evenly spaced samples using either linear interpolation
73/// // or step "interpolation" — i.e. just using the most recent sample as the source of truth.
74/// enum InterpolationMode {
75///     Linear,
76///     Step,
77/// }
78///
79/// // Linear interpolation mode is driven by a trait.
80/// trait LinearInterpolate {
81///     fn lerp(&self, other: &Self, t: f32) -> Self;
82/// }
83///
84/// // Step interpolation just uses an explicit function.
85/// fn step<T: Clone>(first: &T, second: &T, t: f32) -> T {
86///     if t >= 1.0 {
87///         second.clone()
88///     } else {
89///         first.clone()
90///     }
91/// }
92///
93/// // Omitted: Implementing `LinearInterpolate` on relevant types; e.g. `f32`, `Vec3`, and so on.
94///
95/// // The curve itself uses `EvenCore` to hold the evenly-spaced samples, and the `sample_with`
96/// // function will do all the work of interpolating once given a function to do it with.
97/// struct MyCurve<T> {
98///     core: EvenCore<T>,
99///     interpolation_mode: InterpolationMode,
100/// }
101///
102/// impl<T> Curve<T> for MyCurve<T>
103/// where
104///     T: LinearInterpolate + Clone,
105/// {
106///     fn domain(&self) -> Interval {
107///         self.core.domain()
108///     }
109///     
110///     fn sample_unchecked(&self, t: f32) -> T {
111///         // To sample this curve, check the interpolation mode and dispatch accordingly.
112///         match self.interpolation_mode {
113///             InterpolationMode::Linear => self.core.sample_with(t, <T as LinearInterpolate>::lerp),
114///             InterpolationMode::Step => self.core.sample_with(t, step),
115///         }
116///     }
117/// }
118/// ```
119#[cfg(feature = "alloc")]
120#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for EvenCore<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "EvenCore",
            "domain", &self.domain, "samples", &&self.samples)
    }
}Debug, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for EvenCore<T> {
    #[inline]
    fn clone(&self) -> EvenCore<T> {
        EvenCore {
            domain: ::core::clone::Clone::clone(&self.domain),
            samples: ::core::clone::Clone::clone(&self.samples),
        }
    }
}Clone, #[automatically_derived]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for EvenCore<T> {
    #[inline]
    fn eq(&self, other: &EvenCore<T>) -> bool {
        self.domain == other.domain && self.samples == other.samples
    }
}PartialEq)]
121#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<T> _serde::Serialize for EvenCore<T> where T: _serde::Serialize {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer,
                            "EvenCore", false as usize + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "domain", &self.domain)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "samples", &self.samples)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };serde::Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de, T> _serde::Deserialize<'de> for EvenCore<T> where
            T: _serde::Deserialize<'de> {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, __ignore, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            _ => _serde::__private228::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "domain" => _serde::__private228::Ok(__Field::__field0),
                            "samples" => _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"domain" => _serde::__private228::Ok(__Field::__field0),
                            b"samples" => _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de, T> where T: _serde::Deserialize<'de> {
                    marker: _serde::__private228::PhantomData<EvenCore<T>>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
                    where T: _serde::Deserialize<'de> {
                    type Value = EvenCore<T>;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "struct EvenCore")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<Interval>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct EvenCore with 2 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Vec<T>>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct EvenCore with 2 elements")),
                            };
                        _serde::__private228::Ok(EvenCore {
                                domain: __field0,
                                samples: __field1,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0: _serde::__private228::Option<Interval> =
                            _serde::__private228::None;
                        let mut __field1: _serde::__private228::Option<Vec<T>> =
                            _serde::__private228::None;
                        while let _serde::__private228::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private228::Option::is_some(&__field0) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("domain"));
                                    }
                                    __field0 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Interval>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private228::Option::is_some(&__field1) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("samples"));
                                    }
                                    __field1 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<T>>(&mut __map)?);
                                }
                                _ => {
                                    let _ =
                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                }
                            }
                        }
                        let __field0 =
                            match __field0 {
                                _serde::__private228::Some(__field0) => __field0,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("domain")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private228::Some(__field1) => __field1,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("samples")?,
                            };
                        _serde::__private228::Ok(EvenCore {
                                domain: __field0,
                                samples: __field1,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] =
                    &["domain", "samples"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "EvenCore", FIELDS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<EvenCore<T>>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };serde::Deserialize))]
122#[cfg_attr(feature = "bevy_reflect", derive(const _: () =
    {
        impl<T> bevy_reflect::GetTypeRegistration for EvenCore<T> where
            EvenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Interval as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Vec<T> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl<T> bevy_reflect::Typed for EvenCore<T> where
            EvenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Interval>("domain"),
                                                    bevy_reflect::NamedField::new::<Vec<T>>("samples")]).with_generics(bevy_reflect::Generics::from_iter([bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<T>(bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("T")))])))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<T> bevy_reflect::TypePath for EvenCore<T> where
            EvenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_math::curve::cores::EvenCore<"),
                                    <T as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("EvenCore<"),
                                    <T as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("EvenCore")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::curve::cores".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::curve::cores")
            }
        }
        impl<T> bevy_reflect::Reflect for EvenCore<T> where
            EvenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<T> bevy_reflect::structs::Struct for EvenCore<T> where
            EvenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "domain" => ::core::option::Option::Some(&self.domain),
                    "samples" => ::core::option::Option::Some(&self.samples),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "domain" => ::core::option::Option::Some(&mut self.domain),
                    "samples" =>
                        ::core::option::Option::Some(&mut self.samples),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.domain),
                    1usize => ::core::option::Option::Some(&self.samples),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.domain),
                    1usize => ::core::option::Option::Some(&mut self.samples),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("domain"),
                    1usize => ::core::option::Option::Some("samples"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "domain" => ::core::option::Option::Some(0usize),
                    "samples" => ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 2usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("domain",
                    bevy_reflect::PartialReflect::to_dynamic(&self.domain));
                dynamic.insert_boxed("samples",
                    bevy_reflect::PartialReflect::to_dynamic(&self.samples));
                dynamic
            }
        }
        impl<T> bevy_reflect::PartialReflect for EvenCore<T> where
            EvenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::structs::struct_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(Self {
                            domain: <Interval as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.domain)?,
                            samples: <Vec<T> as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.samples)?,
                        }))
            }
        }
        impl<T> bevy_reflect::FromReflect for EvenCore<T> where
            EvenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this =
                        Self {
                            domain: <Interval as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "domain")?)?,
                            samples: <Vec<T> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "samples")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect))]
123pub struct EvenCore<T> {
124    /// The domain over which the samples are taken, which corresponds to the domain of the curve
125    /// formed by interpolating them.
126    ///
127    /// # Invariants
128    /// This must always be a bounded interval; i.e. its endpoints must be finite.
129    pub domain: Interval,
130
131    /// The samples that are interpolated to extract values.
132    ///
133    /// # Invariants
134    /// This must always have a length of at least 2.
135    pub samples: Vec<T>,
136}
137
138/// An error indicating that an [`EvenCore`] could not be constructed.
139#[derive(#[automatically_derived]
impl ::core::fmt::Debug for EvenCoreError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            EvenCoreError::NotEnoughSamples { samples: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "NotEnoughSamples", "samples", &__self_0),
            EvenCoreError::UnboundedDomain =>
                ::core::fmt::Formatter::write_str(f, "UnboundedDomain"),
        }
    }
}Debug, #[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for EvenCoreError {
    fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
        -> ::core::fmt::Result {
        use ::thiserror::__private18::AsDisplay as _;

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            EvenCoreError::NotEnoughSamples { samples } =>
                match (samples.as_display(),) {
                    (__display_samples,) =>
                        __formatter.write_fmt(format_args!("Need at least two samples to create an EvenCore, but {0} were provided",
                                __display_samples)),
                },
            EvenCoreError::UnboundedDomain {} =>
                __formatter.write_str("Cannot create an EvenCore over an unbounded domain"),
        }
    }
}Error)]
140#[error("Could not construct an EvenCore")]
141pub enum EvenCoreError {
142    /// Not enough samples were provided.
143    #[error("Need at least two samples to create an EvenCore, but {samples} were provided")]
144    NotEnoughSamples {
145        /// The number of samples that were provided.
146        samples: usize,
147    },
148
149    /// Unbounded domains are not compatible with `EvenCore`.
150    #[error("Cannot create an EvenCore over an unbounded domain")]
151    UnboundedDomain,
152}
153
154#[cfg(feature = "alloc")]
155impl<T> EvenCore<T> {
156    /// Create a new [`EvenCore`] from the specified `domain` and `samples`. The samples are
157    /// regarded to be evenly spaced within the given domain interval, so that the outermost
158    /// samples form the boundary of that interval. An error is returned if there are not at
159    /// least 2 samples or if the given domain is unbounded.
160    #[inline]
161    pub fn new(
162        domain: Interval,
163        samples: impl IntoIterator<Item = T>,
164    ) -> Result<Self, EvenCoreError> {
165        let samples: Vec<T> = samples.into_iter().collect();
166        if samples.len() < 2 {
167            return Err(EvenCoreError::NotEnoughSamples {
168                samples: samples.len(),
169            });
170        }
171        if !domain.is_bounded() {
172            return Err(EvenCoreError::UnboundedDomain);
173        }
174
175        Ok(EvenCore { domain, samples })
176    }
177
178    /// The domain of the curve derived from this core.
179    #[inline]
180    pub const fn domain(&self) -> Interval {
181        self.domain
182    }
183
184    /// Obtain a value from the held samples using the given `interpolation` to interpolate
185    /// between adjacent samples.
186    ///
187    /// The interpolation takes two values by reference together with a scalar parameter and
188    /// produces an owned value. The expectation is that `interpolation(&x, &y, 0.0)` and
189    /// `interpolation(&x, &y, 1.0)` are equivalent to `x` and `y` respectively.
190    #[inline]
191    pub fn sample_with<I>(&self, t: f32, interpolation: I) -> T
192    where
193        T: Clone,
194        I: Fn(&T, &T, f32) -> T,
195    {
196        match even_interp(self.domain, self.samples.len(), t) {
197            InterpolationDatum::Exact(idx)
198            | InterpolationDatum::LeftTail(idx)
199            | InterpolationDatum::RightTail(idx) => self.samples[idx].clone(),
200            InterpolationDatum::Between(lower_idx, upper_idx, s) => {
201                interpolation(&self.samples[lower_idx], &self.samples[upper_idx], s)
202            }
203        }
204    }
205
206    /// Given a time `t`, obtain a [`InterpolationDatum`] which governs how interpolation might recover
207    /// a sample at time `t`. For example, when a [`Between`] value is returned, its contents can
208    /// be used to interpolate between the two contained values with the given parameter. The other
209    /// variants give additional context about where the value is relative to the family of samples.
210    ///
211    /// [`Between`]: `InterpolationDatum::Between`
212    pub fn sample_interp(&self, t: f32) -> InterpolationDatum<&T> {
213        even_interp(self.domain, self.samples.len(), t).map(|idx| &self.samples[idx])
214    }
215
216    /// Like [`sample_interp`], but the returned values include the sample times. This can be
217    /// useful when sample interpolation is not scale-invariant.
218    ///
219    /// [`sample_interp`]: EvenCore::sample_interp
220    pub fn sample_interp_timed(&self, t: f32) -> InterpolationDatum<(f32, &T)> {
221        let segment_len = self.domain.length() / (self.samples.len() - 1) as f32;
222        even_interp(self.domain, self.samples.len(), t).map(|idx| {
223            (
224                self.domain.start() + segment_len * idx as f32,
225                &self.samples[idx],
226            )
227        })
228    }
229}
230
231/// Given a domain and a number of samples taken over that interval, return an [`InterpolationDatum`]
232/// that governs how samples are extracted relative to the stored data.
233///
234/// `domain` must be a bounded interval (i.e. `domain.is_bounded() == true`).
235///
236/// `samples` must be at least 2.
237///
238/// This function will never panic, but it may return invalid indices if its assumptions are violated.
239pub fn even_interp(domain: Interval, samples: usize, t: f32) -> InterpolationDatum<usize> {
240    let subdivs = samples - 1;
241    let step = domain.length() / subdivs as f32;
242    let t_shifted = t - domain.start();
243    let steps_taken = t_shifted / step;
244
245    if steps_taken <= 0.0 {
246        // To the left side of all the samples.
247        InterpolationDatum::LeftTail(0)
248    } else if steps_taken >= subdivs as f32 {
249        // To the right side of all the samples
250        InterpolationDatum::RightTail(samples - 1)
251    } else {
252        let lower_index = ops::floor(steps_taken) as usize;
253        // This upper index is always valid because `steps_taken` is a finite value
254        // strictly less than `samples - 1`, so its floor is at most `samples - 2`
255        let upper_index = lower_index + 1;
256        let s = ops::fract(steps_taken);
257        InterpolationDatum::Between(lower_index, upper_index, s)
258    }
259}
260
261/// The data core of a curve defined by unevenly-spaced samples or keyframes. The intention is to
262/// use this in concert with implicitly or explicitly-defined interpolation in user-space in
263/// order to implement the curve interface using [`domain`] and [`sample_with`].
264///
265/// The internals are made transparent to give curve authors freedom, but [the provided constructor]
266/// enforces the required invariants, and the methods maintain those invariants.
267///
268/// # Example
269/// ```rust
270/// # use bevy_math::curve::*;
271/// # use bevy_math::curve::cores::*;
272/// // Let's make a curve formed by interpolating rotations.
273/// // We'll support two common modes of interpolation:
274/// // - Normalized linear: First do linear interpolation, then normalize to get a valid rotation.
275/// // - Spherical linear: Interpolate through valid rotations with constant angular velocity.
276/// enum InterpolationMode {
277///     NormalizedLinear,
278///     SphericalLinear,
279/// }
280///
281/// // Our interpolation modes will be driven by traits.
282/// trait NormalizedLinearInterpolate {
283///     fn nlerp(&self, other: &Self, t: f32) -> Self;
284/// }
285///
286/// trait SphericalLinearInterpolate {
287///     fn slerp(&self, other: &Self, t: f32) -> Self;
288/// }
289///
290/// // Omitted: These traits would be implemented for `Rot2`, `Quat`, and other rotation representations.
291///
292/// // The curve itself just needs to use the curve core for keyframes, `UnevenCore`, which handles
293/// // everything except for the explicit interpolation used.
294/// struct RotationCurve<T> {
295///     core: UnevenCore<T>,
296///     interpolation_mode: InterpolationMode,
297/// }
298///
299/// impl<T> Curve<T> for RotationCurve<T>
300/// where
301///     T: NormalizedLinearInterpolate + SphericalLinearInterpolate + Clone,
302/// {
303///     fn domain(&self) -> Interval {
304///         self.core.domain()
305///     }
306///     
307///     fn sample_unchecked(&self, t: f32) -> T {
308///         // To sample the curve, we just look at the interpolation mode and
309///         // dispatch accordingly.
310///         match self.interpolation_mode {
311///             InterpolationMode::NormalizedLinear =>
312///                 self.core.sample_with(t, <T as NormalizedLinearInterpolate>::nlerp),
313///             InterpolationMode::SphericalLinear =>
314///                 self.core.sample_with(t, <T as SphericalLinearInterpolate>::slerp),
315///         }
316///     }
317/// }
318/// ```
319///
320/// [`domain`]: UnevenCore::domain
321/// [`sample_with`]: UnevenCore::sample_with
322/// [the provided constructor]: UnevenCore::new
323#[cfg(feature = "alloc")]
324#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for UnevenCore<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "UnevenCore",
            "times", &self.times, "samples", &&self.samples)
    }
}Debug, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for UnevenCore<T> {
    #[inline]
    fn clone(&self) -> UnevenCore<T> {
        UnevenCore {
            times: ::core::clone::Clone::clone(&self.times),
            samples: ::core::clone::Clone::clone(&self.samples),
        }
    }
}Clone)]
325#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<T> _serde::Serialize for UnevenCore<T> where T: _serde::Serialize
            {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer,
                            "UnevenCore", false as usize + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "times", &self.times)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "samples", &self.samples)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };serde::Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de, T> _serde::Deserialize<'de> for UnevenCore<T> where
            T: _serde::Deserialize<'de> {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, __ignore, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            _ => _serde::__private228::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "times" => _serde::__private228::Ok(__Field::__field0),
                            "samples" => _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"times" => _serde::__private228::Ok(__Field::__field0),
                            b"samples" => _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de, T> where T: _serde::Deserialize<'de> {
                    marker: _serde::__private228::PhantomData<UnevenCore<T>>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
                    where T: _serde::Deserialize<'de> {
                    type Value = UnevenCore<T>;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "struct UnevenCore")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<Vec<f32>>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct UnevenCore with 2 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Vec<T>>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct UnevenCore with 2 elements")),
                            };
                        _serde::__private228::Ok(UnevenCore {
                                times: __field0,
                                samples: __field1,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0: _serde::__private228::Option<Vec<f32>> =
                            _serde::__private228::None;
                        let mut __field1: _serde::__private228::Option<Vec<T>> =
                            _serde::__private228::None;
                        while let _serde::__private228::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private228::Option::is_some(&__field0) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("times"));
                                    }
                                    __field0 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<f32>>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private228::Option::is_some(&__field1) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("samples"));
                                    }
                                    __field1 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<T>>(&mut __map)?);
                                }
                                _ => {
                                    let _ =
                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                }
                            }
                        }
                        let __field0 =
                            match __field0 {
                                _serde::__private228::Some(__field0) => __field0,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("times")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private228::Some(__field1) => __field1,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("samples")?,
                            };
                        _serde::__private228::Ok(UnevenCore {
                                times: __field0,
                                samples: __field1,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] = &["times", "samples"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "UnevenCore", FIELDS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<UnevenCore<T>>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };serde::Deserialize))]
326#[cfg_attr(feature = "bevy_reflect", derive(const _: () =
    {
        impl<T> bevy_reflect::GetTypeRegistration for UnevenCore<T> where
            UnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Vec<f32> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Vec<T> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl<T> bevy_reflect::Typed for UnevenCore<T> where
            UnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Vec<f32>>("times"),
                                                    bevy_reflect::NamedField::new::<Vec<T>>("samples")]).with_generics(bevy_reflect::Generics::from_iter([bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<T>(bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("T")))])))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<T> bevy_reflect::TypePath for UnevenCore<T> where
            UnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_math::curve::cores::UnevenCore<"),
                                    <T as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("UnevenCore<"),
                                    <T as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("UnevenCore")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::curve::cores".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::curve::cores")
            }
        }
        impl<T> bevy_reflect::Reflect for UnevenCore<T> where
            UnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<T> bevy_reflect::structs::Struct for UnevenCore<T> where
            UnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "times" => ::core::option::Option::Some(&self.times),
                    "samples" => ::core::option::Option::Some(&self.samples),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "times" => ::core::option::Option::Some(&mut self.times),
                    "samples" =>
                        ::core::option::Option::Some(&mut self.samples),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.times),
                    1usize => ::core::option::Option::Some(&self.samples),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.times),
                    1usize => ::core::option::Option::Some(&mut self.samples),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("times"),
                    1usize => ::core::option::Option::Some("samples"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "times" => ::core::option::Option::Some(0usize),
                    "samples" => ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 2usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("times",
                    bevy_reflect::PartialReflect::to_dynamic(&self.times));
                dynamic.insert_boxed("samples",
                    bevy_reflect::PartialReflect::to_dynamic(&self.samples));
                dynamic
            }
        }
        impl<T> bevy_reflect::PartialReflect for UnevenCore<T> where
            UnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::structs::struct_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(Self {
                            times: <Vec<f32> as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.times)?,
                            samples: <Vec<T> as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.samples)?,
                        }))
            }
        }
        impl<T> bevy_reflect::FromReflect for UnevenCore<T> where
            UnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this =
                        Self {
                            times: <Vec<f32> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "times")?)?,
                            samples: <Vec<T> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "samples")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect))]
327pub struct UnevenCore<T> {
328    /// The times for the samples of this curve.
329    ///
330    /// # Invariants
331    /// This must always have a length of at least 2, be sorted, and have no
332    /// duplicated or non-finite times.
333    pub times: Vec<f32>,
334
335    /// The samples corresponding to the times for this curve.
336    ///
337    /// # Invariants
338    /// This must always have the same length as `times`.
339    pub samples: Vec<T>,
340}
341
342/// An error indicating that an [`UnevenCore`] could not be constructed.
343#[derive(#[automatically_derived]
impl ::core::fmt::Debug for UnevenCoreError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            UnevenCoreError::NotEnoughSamples { samples: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "NotEnoughSamples", "samples", &__self_0),
        }
    }
}Debug, #[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for UnevenCoreError {
    fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
        -> ::core::fmt::Result {
        use ::thiserror::__private18::AsDisplay as _;

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            UnevenCoreError::NotEnoughSamples { samples } =>
                match (samples.as_display(),) {
                    (__display_samples,) =>
                        __formatter.write_fmt(format_args!("Need at least two unique samples to create an UnevenCore, but {0} were provided",
                                __display_samples)),
                },
        }
    }
}Error)]
344#[error("Could not construct an UnevenCore")]
345pub enum UnevenCoreError {
346    /// Not enough samples were provided.
347    #[error(
348        "Need at least two unique samples to create an UnevenCore, but {samples} were provided"
349    )]
350    NotEnoughSamples {
351        /// The number of samples that were provided.
352        samples: usize,
353    },
354}
355
356#[cfg(feature = "alloc")]
357impl<T> UnevenCore<T> {
358    /// Create a new [`UnevenCore`]. The given samples are filtered to finite times and
359    /// sorted internally; if there are not at least 2 valid timed samples, an error will be
360    /// returned.
361    pub fn new(timed_samples: impl IntoIterator<Item = (f32, T)>) -> Result<Self, UnevenCoreError> {
362        // Filter out non-finite sample times first so they don't interfere with sorting/deduplication.
363        let mut timed_samples = timed_samples
364            .into_iter()
365            .filter(|(t, _)| t.is_finite())
366            .collect_vec();
367        timed_samples
368            // Using `total_cmp` is fine because no NANs remain and because deduplication uses
369            // `PartialEq` anyway (so -0.0 and 0.0 will be considered equal later regardless).
370            .sort_by(|(t0, _), (t1, _)| t0.total_cmp(t1));
371        timed_samples.dedup_by_key(|(t, _)| *t);
372
373        if timed_samples.len() < 2 {
374            return Err(UnevenCoreError::NotEnoughSamples {
375                samples: timed_samples.len(),
376            });
377        }
378
379        let (times, samples): (Vec<f32>, Vec<T>) = timed_samples.into_iter().unzip();
380        Ok(UnevenCore { times, samples })
381    }
382
383    /// The domain of the curve derived from this core.
384    ///
385    /// # Panics
386    /// This method may panic if the type's invariants aren't satisfied.
387    #[inline]
388    pub fn domain(&self) -> Interval {
389        let start = self.times.first().unwrap();
390        let end = self.times.last().unwrap();
391        Interval::new(*start, *end).unwrap()
392    }
393
394    /// Obtain a value from the held samples using the given `interpolation` to interpolate
395    /// between adjacent samples.
396    ///
397    /// The interpolation takes two values by reference together with a scalar parameter and
398    /// produces an owned value. The expectation is that `interpolation(&x, &y, 0.0)` and
399    /// `interpolation(&x, &y, 1.0)` are equivalent to `x` and `y` respectively.
400    #[inline]
401    pub fn sample_with<I>(&self, t: f32, interpolation: I) -> T
402    where
403        T: Clone,
404        I: Fn(&T, &T, f32) -> T,
405    {
406        match uneven_interp(&self.times, t) {
407            InterpolationDatum::Exact(idx)
408            | InterpolationDatum::LeftTail(idx)
409            | InterpolationDatum::RightTail(idx) => self.samples[idx].clone(),
410            InterpolationDatum::Between(lower_idx, upper_idx, s) => {
411                interpolation(&self.samples[lower_idx], &self.samples[upper_idx], s)
412            }
413        }
414    }
415
416    /// Given a time `t`, obtain a [`InterpolationDatum`] which governs how interpolation might recover
417    /// a sample at time `t`. For example, when a [`Between`] value is returned, its contents can
418    /// be used to interpolate between the two contained values with the given parameter. The other
419    /// variants give additional context about where the value is relative to the family of samples.
420    ///
421    /// [`Between`]: `InterpolationDatum::Between`
422    pub fn sample_interp(&self, t: f32) -> InterpolationDatum<&T> {
423        uneven_interp(&self.times, t).map(|idx| &self.samples[idx])
424    }
425
426    /// Like [`sample_interp`], but the returned values include the sample times. This can be
427    /// useful when sample interpolation is not scale-invariant.
428    ///
429    /// [`sample_interp`]: UnevenCore::sample_interp
430    pub fn sample_interp_timed(&self, t: f32) -> InterpolationDatum<(f32, &T)> {
431        uneven_interp(&self.times, t).map(|idx| (self.times[idx], &self.samples[idx]))
432    }
433
434    /// This core, but with the sample times moved by the map `f`.
435    /// In principle, when `f` is monotone, this is equivalent to [`CurveExt::reparametrize`],
436    /// but the function inputs to each are inverses of one another.
437    ///
438    /// The samples are re-sorted by time after mapping and deduplicated by output time, so
439    /// the function `f` should generally be injective over the set of sample times, otherwise
440    /// data will be deleted.
441    ///
442    /// [`CurveExt::reparametrize`]: crate::curve::CurveExt::reparametrize
443    #[must_use]
444    pub fn map_sample_times(mut self, f: impl Fn(f32) -> f32) -> UnevenCore<T> {
445        let mut timed_samples = self
446            .times
447            .into_iter()
448            .map(f)
449            .zip(self.samples)
450            .collect_vec();
451        timed_samples.sort_by(|(t1, _), (t2, _)| t1.total_cmp(t2));
452        timed_samples.dedup_by_key(|(t, _)| *t);
453        (self.times, self.samples) = timed_samples.into_iter().unzip();
454        self
455    }
456}
457
458/// The data core of a curve using uneven samples (i.e. keyframes), where each sample time
459/// yields some fixed number of values — the [sampling width]. This may serve as storage for
460/// curves that yield vectors or iterators, and in some cases, it may be useful for cache locality
461/// if the sample type can effectively be encoded as a fixed-length slice of values.
462///
463/// [sampling width]: ChunkedUnevenCore::width
464#[cfg(feature = "alloc")]
465#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ChunkedUnevenCore<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "ChunkedUnevenCore", "times", &self.times, "values",
            &&self.values)
    }
}Debug, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for ChunkedUnevenCore<T> {
    #[inline]
    fn clone(&self) -> ChunkedUnevenCore<T> {
        ChunkedUnevenCore {
            times: ::core::clone::Clone::clone(&self.times),
            values: ::core::clone::Clone::clone(&self.values),
        }
    }
}Clone)]
466#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<T> _serde::Serialize for ChunkedUnevenCore<T> where
            T: _serde::Serialize {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer,
                            "ChunkedUnevenCore", false as usize + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "times", &self.times)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "values", &self.values)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };serde::Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de, T> _serde::Deserialize<'de> for ChunkedUnevenCore<T> where
            T: _serde::Deserialize<'de> {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, __ignore, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            _ => _serde::__private228::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "times" => _serde::__private228::Ok(__Field::__field0),
                            "values" => _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"times" => _serde::__private228::Ok(__Field::__field0),
                            b"values" => _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de, T> where T: _serde::Deserialize<'de> {
                    marker: _serde::__private228::PhantomData<ChunkedUnevenCore<T>>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
                    where T: _serde::Deserialize<'de> {
                    type Value = ChunkedUnevenCore<T>;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "struct ChunkedUnevenCore")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<Vec<f32>>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct ChunkedUnevenCore with 2 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Vec<T>>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct ChunkedUnevenCore with 2 elements")),
                            };
                        _serde::__private228::Ok(ChunkedUnevenCore {
                                times: __field0,
                                values: __field1,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0: _serde::__private228::Option<Vec<f32>> =
                            _serde::__private228::None;
                        let mut __field1: _serde::__private228::Option<Vec<T>> =
                            _serde::__private228::None;
                        while let _serde::__private228::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private228::Option::is_some(&__field0) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("times"));
                                    }
                                    __field0 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<f32>>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private228::Option::is_some(&__field1) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("values"));
                                    }
                                    __field1 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec<T>>(&mut __map)?);
                                }
                                _ => {
                                    let _ =
                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                }
                            }
                        }
                        let __field0 =
                            match __field0 {
                                _serde::__private228::Some(__field0) => __field0,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("times")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private228::Some(__field1) => __field1,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("values")?,
                            };
                        _serde::__private228::Ok(ChunkedUnevenCore {
                                times: __field0,
                                values: __field1,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] = &["times", "values"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "ChunkedUnevenCore", FIELDS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<ChunkedUnevenCore<T>>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };serde::Deserialize))]
467#[cfg_attr(feature = "bevy_reflect", derive(const _: () =
    {
        impl<T> bevy_reflect::GetTypeRegistration for ChunkedUnevenCore<T>
            where ChunkedUnevenCore<T>: ::core::any::Any +
            ::core::marker::Send + ::core::marker::Sync,
            T: bevy_reflect::TypePath, Vec<T>: bevy_reflect::FromReflect +
            bevy_reflect::TypePath + bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Vec<f32> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
                <Vec<T> as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl<T> bevy_reflect::Typed for ChunkedUnevenCore<T> where
            ChunkedUnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::GenericTypeInfoCell =
                    bevy_reflect::utility::GenericTypeInfoCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Vec<f32>>("times"),
                                                    bevy_reflect::NamedField::new::<Vec<T>>("values")]).with_generics(bevy_reflect::Generics::from_iter([bevy_reflect::GenericInfo::Type(bevy_reflect::TypeParamInfo::new::<T>(bevy_reflect::__macro_exports::alloc_utils::Cow::Borrowed("T")))])))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl<T> bevy_reflect::TypePath for ChunkedUnevenCore<T> where
            ChunkedUnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath {
            fn type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("bevy_math::curve::cores::ChunkedUnevenCore<"),
                                    <T as bevy_reflect::TypePath>::type_path()), ">")
                        })
            }
            fn short_type_path() -> &'static str {
                static CELL: bevy_reflect::utility::GenericTypePathCell =
                    bevy_reflect::utility::GenericTypePathCell::new();
                CELL.get_or_insert::<Self,
                    _>(||
                        {
                            ::core::ops::Add::<&str>::add(::core::ops::Add::<&str>::add(bevy_reflect::__macro_exports::alloc_utils::ToString::to_string("ChunkedUnevenCore<"),
                                    <T as bevy_reflect::TypePath>::short_type_path()), ">")
                        })
            }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("ChunkedUnevenCore")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::curve::cores".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::curve::cores")
            }
        }
        impl<T> bevy_reflect::Reflect for ChunkedUnevenCore<T> where
            ChunkedUnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl<T> bevy_reflect::structs::Struct for ChunkedUnevenCore<T> where
            ChunkedUnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "times" => ::core::option::Option::Some(&self.times),
                    "values" => ::core::option::Option::Some(&self.values),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "times" => ::core::option::Option::Some(&mut self.times),
                    "values" => ::core::option::Option::Some(&mut self.values),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.times),
                    1usize => ::core::option::Option::Some(&self.values),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.times),
                    1usize => ::core::option::Option::Some(&mut self.values),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("times"),
                    1usize => ::core::option::Option::Some("values"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "times" => ::core::option::Option::Some(0usize),
                    "values" => ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 2usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("times",
                    bevy_reflect::PartialReflect::to_dynamic(&self.times));
                dynamic.insert_boxed("values",
                    bevy_reflect::PartialReflect::to_dynamic(&self.values));
                dynamic
            }
        }
        impl<T> bevy_reflect::PartialReflect for ChunkedUnevenCore<T> where
            ChunkedUnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                (bevy_reflect::structs::struct_partial_eq)(self, value)
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            #[inline]
            #[allow(unreachable_code, reason =
            "Ignored fields without a `clone` attribute will early-return with an error")]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(Self {
                            times: <Vec<f32> as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.times)?,
                            values: <Vec<T> as
                                        bevy_reflect::PartialReflect>::reflect_clone_and_take(&self.values)?,
                        }))
            }
        }
        impl<T> bevy_reflect::FromReflect for ChunkedUnevenCore<T> where
            ChunkedUnevenCore<T>: ::core::any::Any + ::core::marker::Send +
            ::core::marker::Sync, T: bevy_reflect::TypePath,
            Vec<T>: bevy_reflect::FromReflect + bevy_reflect::TypePath +
            bevy_reflect::MaybeTyped +
            bevy_reflect::__macro_exports::RegisterForReflection {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let __this =
                        Self {
                            times: <Vec<f32> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "times")?)?,
                            values: <Vec<T> as
                                        bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                            "values")?)?,
                        };
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect))]
468pub struct ChunkedUnevenCore<T> {
469    /// The times, one for each sample.
470    ///
471    /// # Invariants
472    /// This must always have a length of at least 2, be sorted, and have no duplicated or
473    /// non-finite times.
474    pub times: Vec<f32>,
475
476    /// The values that are used in sampling. Each width-worth of these correspond to a single sample.
477    ///
478    /// # Invariants
479    /// The length of this vector must always be some fixed integer multiple of that of `times`.
480    pub values: Vec<T>,
481}
482
483/// An error that indicates that a [`ChunkedUnevenCore`] could not be formed.
484#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ChunkedUnevenCoreError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ChunkedUnevenCoreError::ZeroWidth =>
                ::core::fmt::Formatter::write_str(f, "ZeroWidth"),
            ChunkedUnevenCoreError::NotEnoughSamples { samples: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "NotEnoughSamples", "samples", &__self_0),
            ChunkedUnevenCoreError::MismatchedLengths {
                expected: __self_0, actual: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "MismatchedLengths", "expected", __self_0, "actual",
                    &__self_1),
            ChunkedUnevenCoreError::NonDivisibleLengths {
                values_len: __self_0, times_len: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "NonDivisibleLengths", "values_len", __self_0, "times_len",
                    &__self_1),
        }
    }
}Debug, #[allow(unused_qualifications)]
#[automatically_derived]
impl ::core::fmt::Display for ChunkedUnevenCoreError {
    fn fmt(&self, __formatter: &mut ::core::fmt::Formatter)
        -> ::core::fmt::Result {
        use ::thiserror::__private18::AsDisplay as _;

        #[allow(unused_variables, deprecated, clippy ::
        used_underscore_binding)]
        match self {
            ChunkedUnevenCoreError::ZeroWidth {} =>
                __formatter.write_str("Chunk width must be at least 1"),
            ChunkedUnevenCoreError::NotEnoughSamples { samples } =>
                match (samples.as_display(),) {
                    (__display_samples,) =>
                        __formatter.write_fmt(format_args!("Need at least two unique samples to create a ChunkedUnevenCore, but {0} were provided",
                                __display_samples)),
                },
            ChunkedUnevenCoreError::MismatchedLengths { expected, actual } =>
                match (expected.as_display(), actual.as_display()) {
                    (__display_expected, __display_actual) =>
                        __formatter.write_fmt(format_args!("Expected {0} total values based on width, but {1} were provided",
                                __display_expected, __display_actual)),
                },
            ChunkedUnevenCoreError::NonDivisibleLengths {
                values_len, times_len } =>
                match (values_len.as_display(), times_len.as_display()) {
                    (__display_values_len, __display_times_len) =>
                        __formatter.write_fmt(format_args!("The length of the list of values ({0}) was not divisible by that of the list of times ({1})",
                                __display_values_len, __display_times_len)),
                },
        }
    }
}Error)]
485#[error("Could not create a ChunkedUnevenCore")]
486pub enum ChunkedUnevenCoreError {
487    /// The width of a `ChunkedUnevenCore` cannot be zero.
488    #[error("Chunk width must be at least 1")]
489    ZeroWidth,
490
491    /// At least two sample times are necessary to interpolate in `ChunkedUnevenCore`.
492    #[error(
493        "Need at least two unique samples to create a ChunkedUnevenCore, but {samples} were provided"
494    )]
495    NotEnoughSamples {
496        /// The number of samples that were provided.
497        samples: usize,
498    },
499
500    /// The length of the value buffer is supposed to be the `width` times the number of samples.
501    #[error("Expected {expected} total values based on width, but {actual} were provided")]
502    MismatchedLengths {
503        /// The expected length of the value buffer.
504        expected: usize,
505        /// The actual length of the value buffer.
506        actual: usize,
507    },
508
509    /// Tried to infer the width, but the ratio of lengths wasn't an integer, so no such length exists.
510    #[error("The length of the list of values ({values_len}) was not divisible by that of the list of times ({times_len})")]
511    NonDivisibleLengths {
512        /// The length of the value buffer.
513        values_len: usize,
514        /// The length of the time buffer.
515        times_len: usize,
516    },
517}
518
519#[cfg(feature = "alloc")]
520impl<T> ChunkedUnevenCore<T> {
521    /// Create a new [`ChunkedUnevenCore`]. The given `times` are sorted, filtered to finite times,
522    /// and deduplicated. See the [type-level documentation] for more information about this type.
523    ///
524    /// Produces an error in any of the following circumstances:
525    /// - `width` is zero.
526    /// - `times` has less than `2` unique valid entries.
527    /// - `values` has the incorrect length relative to `times`.
528    ///
529    /// [type-level documentation]: ChunkedUnevenCore
530    pub fn new(
531        times: impl IntoIterator<Item = f32>,
532        values: impl IntoIterator<Item = T>,
533        width: usize,
534    ) -> Result<Self, ChunkedUnevenCoreError> {
535        let times = times.into_iter().collect_vec();
536        let values = values.into_iter().collect_vec();
537
538        if width == 0 {
539            return Err(ChunkedUnevenCoreError::ZeroWidth);
540        }
541
542        let times = filter_sort_dedup_times(times);
543
544        if times.len() < 2 {
545            return Err(ChunkedUnevenCoreError::NotEnoughSamples {
546                samples: times.len(),
547            });
548        }
549
550        if values.len() != times.len() * width {
551            return Err(ChunkedUnevenCoreError::MismatchedLengths {
552                expected: times.len() * width,
553                actual: values.len(),
554            });
555        }
556
557        Ok(Self { times, values })
558    }
559
560    /// Create a new [`ChunkedUnevenCore`], inferring the width from the sizes of the inputs.
561    /// The given `times` are sorted, filtered to finite times, and deduplicated. See the
562    /// [type-level documentation] for more information about this type. Prefer using [`new`]
563    /// if possible, since that constructor has richer error checking.
564    ///
565    /// Produces an error in any of the following circumstances:
566    /// - `values` has length zero.
567    /// - `times` has less than `2` unique valid entries.
568    /// - The length of `values` is not divisible by that of `times` (once sorted, filtered,
569    ///   and deduplicated).
570    ///
571    /// The [width] is implicitly taken to be the length of `values` divided by that of `times`
572    /// (once sorted, filtered, and deduplicated).
573    ///
574    /// [type-level documentation]: ChunkedUnevenCore
575    /// [`new`]: ChunkedUnevenCore::new
576    /// [width]: ChunkedUnevenCore::width
577    pub fn new_width_inferred(
578        times: impl IntoIterator<Item = f32>,
579        values: impl IntoIterator<Item = T>,
580    ) -> Result<Self, ChunkedUnevenCoreError> {
581        let times = times.into_iter().collect_vec();
582        let values = values.into_iter().collect_vec();
583
584        let times = filter_sort_dedup_times(times);
585
586        if times.len() < 2 {
587            return Err(ChunkedUnevenCoreError::NotEnoughSamples {
588                samples: times.len(),
589            });
590        }
591
592        if !values.len().is_multiple_of(times.len()) {
593            return Err(ChunkedUnevenCoreError::NonDivisibleLengths {
594                values_len: values.len(),
595                times_len: times.len(),
596            });
597        }
598
599        if values.is_empty() {
600            return Err(ChunkedUnevenCoreError::ZeroWidth);
601        }
602
603        Ok(Self { times, values })
604    }
605
606    /// The domain of the curve derived from this core.
607    ///
608    /// # Panics
609    /// This may panic if this type's invariants aren't met.
610    #[inline]
611    pub fn domain(&self) -> Interval {
612        let start = self.times.first().unwrap();
613        let end = self.times.last().unwrap();
614        Interval::new(*start, *end).unwrap()
615    }
616
617    /// The sample width: the number of values that are contained in each sample.
618    #[inline]
619    pub fn width(&self) -> usize {
620        self.values.len() / self.times.len()
621    }
622
623    /// Given a time `t`, obtain a [`InterpolationDatum`] which governs how interpolation might recover
624    /// a sample at time `t`. For example, when a [`Between`] value is returned, its contents can
625    /// be used to interpolate between the two contained values with the given parameter. The other
626    /// variants give additional context about where the value is relative to the family of samples.
627    ///
628    /// [`Between`]: `InterpolationDatum::Between`
629    #[inline]
630    pub fn sample_interp(&self, t: f32) -> InterpolationDatum<&[T]> {
631        uneven_interp(&self.times, t).map(|idx| self.time_index_to_slice(idx))
632    }
633
634    /// Like [`sample_interp`], but the returned values include the sample times. This can be
635    /// useful when sample interpolation is not scale-invariant.
636    ///
637    /// [`sample_interp`]: ChunkedUnevenCore::sample_interp
638    pub fn sample_interp_timed(&self, t: f32) -> InterpolationDatum<(f32, &[T])> {
639        uneven_interp(&self.times, t).map(|idx| (self.times[idx], self.time_index_to_slice(idx)))
640    }
641
642    /// Given an index in [times], returns the slice of [values] that correspond to the sample at
643    /// that time.
644    ///
645    /// [times]: ChunkedUnevenCore::times
646    /// [values]: ChunkedUnevenCore::values
647    #[inline]
648    fn time_index_to_slice(&self, idx: usize) -> &[T] {
649        let width = self.width();
650        let lower_idx = width * idx;
651        let upper_idx = lower_idx + width;
652        &self.values[lower_idx..upper_idx]
653    }
654}
655
656/// Sort the given times, deduplicate them, and filter them to only finite times.
657#[cfg(feature = "alloc")]
658fn filter_sort_dedup_times(times: impl IntoIterator<Item = f32>) -> Vec<f32> {
659    // Filter before sorting/deduplication so that NAN doesn't interfere with them.
660    let mut times = times.into_iter().filter(|t| t.is_finite()).collect_vec();
661    times.sort_by(f32::total_cmp);
662    times.dedup();
663    times
664}
665
666/// Given a list of `times` and a target value, get the interpolation relationship for the
667/// target value in terms of the indices of the starting list. In a sense, this encapsulates the
668/// heart of uneven/keyframe sampling.
669///
670/// `times` is assumed to be sorted, deduplicated, and consisting only of finite values. It is also
671/// assumed to contain at least two values.
672///
673/// # Panics
674/// This function will panic if `times` contains NAN.
675pub fn uneven_interp(times: &[f32], t: f32) -> InterpolationDatum<usize> {
676    match times.binary_search_by(|pt| pt.partial_cmp(&t).unwrap()) {
677        Ok(index) => InterpolationDatum::Exact(index),
678        Err(index) => {
679            if index == 0 {
680                // This is before the first keyframe.
681                InterpolationDatum::LeftTail(0)
682            } else if index >= times.len() {
683                // This is after the last keyframe.
684                InterpolationDatum::RightTail(times.len() - 1)
685            } else {
686                // This is actually in the middle somewhere.
687                let t_lower = times[index - 1];
688                let t_upper = times[index];
689                let s = (t - t_lower) / (t_upper - t_lower);
690                InterpolationDatum::Between(index - 1, index, s)
691            }
692        }
693    }
694}
695
696#[cfg(all(test, feature = "alloc"))]
697mod tests {
698    use super::{ChunkedUnevenCore, EvenCore, UnevenCore};
699    use crate::curve::{cores::InterpolationDatum, interval};
700    use alloc::vec;
701    use approx::{assert_abs_diff_eq, AbsDiffEq};
702
703    fn approx_between<T>(datum: InterpolationDatum<T>, start: T, end: T, p: f32) -> bool
704    where
705        T: PartialEq,
706    {
707        if let InterpolationDatum::Between(m_start, m_end, m_p) = datum {
708            m_start == start && m_end == end && m_p.abs_diff_eq(&p, 1e-6)
709        } else {
710            false
711        }
712    }
713
714    fn is_left_tail<T>(datum: InterpolationDatum<T>) -> bool {
715        matches!(datum, InterpolationDatum::LeftTail(_))
716    }
717
718    fn is_right_tail<T>(datum: InterpolationDatum<T>) -> bool {
719        matches!(datum, InterpolationDatum::RightTail(_))
720    }
721
722    fn is_exact<T>(datum: InterpolationDatum<T>, target: T) -> bool
723    where
724        T: PartialEq,
725    {
726        if let InterpolationDatum::Exact(v) = datum {
727            v == target
728        } else {
729            false
730        }
731    }
732
733    #[test]
734    fn even_sample_interp() {
735        let even_core = EvenCore::<f32>::new(
736            interval(0.0, 1.0).unwrap(),
737            // 11 entries -> 10 segments
738            vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
739        )
740        .expect("Failed to construct test core");
741
742        let datum = even_core.sample_interp(-1.0);
743        assert!(is_left_tail(datum));
744        let datum = even_core.sample_interp(0.0);
745        assert!(is_left_tail(datum));
746        let datum = even_core.sample_interp(1.0);
747        assert!(is_right_tail(datum));
748        let datum = even_core.sample_interp(2.0);
749        assert!(is_right_tail(datum));
750
751        let datum = even_core.sample_interp(0.05);
752        let InterpolationDatum::Between(0.0, 1.0, p) = datum else {
753            panic!("Sample did not lie in the correct subinterval")
754        };
755        assert_abs_diff_eq!(p, 0.5);
756
757        let datum = even_core.sample_interp(0.05);
758        assert!(approx_between(datum, &0.0, &1.0, 0.5));
759        let datum = even_core.sample_interp(0.33);
760        assert!(approx_between(datum, &3.0, &4.0, 0.3));
761        let datum = even_core.sample_interp(0.78);
762        assert!(approx_between(datum, &7.0, &8.0, 0.8));
763
764        let datum = even_core.sample_interp(0.5);
765        assert!(approx_between(datum, &4.0, &5.0, 1.0) || approx_between(datum, &5.0, &6.0, 0.0));
766        let datum = even_core.sample_interp(0.7);
767        assert!(approx_between(datum, &6.0, &7.0, 1.0) || approx_between(datum, &7.0, &8.0, 0.0));
768    }
769
770    #[test]
771    fn uneven_sample_interp() {
772        let uneven_core = UnevenCore::<f32>::new(vec![
773            (0.0, 0.0),
774            (1.0, 3.0),
775            (2.0, 9.0),
776            (4.0, 10.0),
777            (8.0, -5.0),
778        ])
779        .expect("Failed to construct test core");
780
781        let datum = uneven_core.sample_interp(-1.0);
782        assert!(is_left_tail(datum));
783        let datum = uneven_core.sample_interp(0.0);
784        assert!(is_exact(datum, &0.0));
785        let datum = uneven_core.sample_interp(8.0);
786        assert!(is_exact(datum, &(-5.0)));
787        let datum = uneven_core.sample_interp(9.0);
788        assert!(is_right_tail(datum));
789
790        let datum = uneven_core.sample_interp(0.5);
791        assert!(approx_between(datum, &0.0, &3.0, 0.5));
792        let datum = uneven_core.sample_interp(2.5);
793        assert!(approx_between(datum, &9.0, &10.0, 0.25));
794        let datum = uneven_core.sample_interp(7.0);
795        assert!(approx_between(datum, &10.0, &(-5.0), 0.75));
796
797        let datum = uneven_core.sample_interp(2.0);
798        assert!(is_exact(datum, &9.0));
799        let datum = uneven_core.sample_interp(4.0);
800        assert!(is_exact(datum, &10.0));
801    }
802
803    #[test]
804    fn chunked_uneven_sample_interp() {
805        let core =
806            ChunkedUnevenCore::new(vec![0.0, 2.0, 8.0], vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0], 2)
807                .expect("Failed to construct test core");
808
809        let datum = core.sample_interp(-1.0);
810        assert!(is_left_tail(datum));
811        let datum = core.sample_interp(0.0);
812        assert!(is_exact(datum, &[0.0, 1.0]));
813        let datum = core.sample_interp(8.0);
814        assert!(is_exact(datum, &[4.0, 5.0]));
815        let datum = core.sample_interp(10.0);
816        assert!(is_right_tail(datum));
817
818        let datum = core.sample_interp(1.0);
819        assert!(approx_between(datum, &[0.0, 1.0], &[2.0, 3.0], 0.5));
820        let datum = core.sample_interp(3.0);
821        assert!(approx_between(datum, &[2.0, 3.0], &[4.0, 5.0], 1.0 / 6.0));
822
823        let datum = core.sample_interp(2.0);
824        assert!(is_exact(datum, &[2.0, 3.0]));
825    }
826}