Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 37 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ path = "src/lib.rs"

[features]
default = ["std", "macros"]
std = ["matrixmultiply", "num-traits/std", "num-complex/std", "num-rational/std", "approx/std", "simba/std"]
std = [
"matrixmultiply",
"num-traits/std",
"num-complex/std",
"num-rational/std",
"approx/std",
"simba/std",
]
sparse = []
debug = ["approx/num-complex", "rand"]
alloc = []
Expand Down Expand Up @@ -60,20 +67,31 @@ convert-glam030 = ["glam030"]
## `serde-serialize`.
serde-serialize-no-std = ["serde", "num-complex/serde"]
serde-serialize = ["serde-serialize-no-std", "serde/std"]
rkyv-serialize-no-std = ["rkyv/size_32"]
rkyv-serialize = ["rkyv-serialize-no-std", "rkyv/std", "rkyv/validation"]
rkyv-serialize-no-std = ["rkyv/pointer_width_32"]
rkyv-serialize = [
"rkyv-serialize-no-std",
"rkyv/std",
"rkyv/bytecheck",
"dep:bytecheck",
]

# Randomness
## To use rand in a #[no-std] environment, enable the
## `rand-no-std` feature instead of `rand`.
rand-no-std = ["rand-package"]
rand = ["rand-no-std", "rand-package/std", "rand-package/std_rng", "rand-package/thread_rng", "rand_distr"]
rand = [
"rand-no-std",
"rand-package/std",
"rand-package/std_rng",
"rand-package/thread_rng",
"rand_distr",
]

# Tests
arbitrary = ["quickcheck"]
proptest-support = ["proptest"]
slow-tests = []
rkyv-safe-deser = ["rkyv-serialize", "rkyv/validation"]
rkyv-safe-deser = ["rkyv-serialize"]

[dependencies]
nalgebra-macros = { version = "0.2.2", path = "nalgebra-macros", optional = true }
Expand All @@ -87,15 +105,20 @@ simba = { version = "0.9", default-features = false }
alga = { version = "0.9", default-features = false, optional = true }
rand_distr = { version = "0.5", default-features = false, optional = true }
matrixmultiply = { version = "0.3", optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }
rkyv = { version = "0.7.41", default-features = false, optional = true }
serde = { version = "1.0", default-features = false, features = [
"derive",
], optional = true }
rkyv = { version = "0.8", default-features = false, optional = true }
mint = { version = "0.5", optional = true }
quickcheck = { version = "1", optional = true }
pest = { version = "2", optional = true }
pest_derive = { version = "2", optional = true }
bytemuck = { version = "1.5", optional = true }
bytecheck = { version = "0.8", optional = true }
matrixcompare-core = { version = "0.1", optional = true }
proptest = { version = "1", optional = true, default-features = false, features = ["std"] }
proptest = { version = "1", optional = true, default-features = false, features = [
"std",
] }
glam014 = { package = "glam", version = "0.14", optional = true }
glam015 = { package = "glam", version = "0.15", optional = true }
glam016 = { package = "glam", version = "0.16", optional = true }
Expand Down Expand Up @@ -131,7 +154,12 @@ trybuild = "1.0.90"
cool_asserts = "2.0.3"

[workspace]
members = ["nalgebra-lapack", "nalgebra-glm", "nalgebra-sparse", "nalgebra-macros"]
members = [
"nalgebra-lapack",
"nalgebra-glm",
"nalgebra-sparse",
"nalgebra-macros",
]
resolver = "2"

[[example]]
Expand Down
36 changes: 25 additions & 11 deletions src/base/array_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "serde-serialize-no-std")]
use std::marker::PhantomData;

#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;

use crate::base::allocator::Allocator;
use crate::base::default_allocator::DefaultAllocator;
use crate::base::dimension::{Const, ToTypenum};
Expand All @@ -32,16 +29,15 @@ use std::mem;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
archive(
as = "ArrayStorage<T::Archived, R, C>",
bound(archive = "
T: rkyv::Archive,
[[T; R]; C]: rkyv::Archive<Archived = [[T::Archived; R]; C]>
")
derive(rkyv::Archive, rkyv::Portable, rkyv::Serialize, rkyv::Deserialize, bytecheck::CheckBytes),
rkyv(
as = ArrayStorage<T::Archived, R, C>,
archive_bounds(
T: rkyv::Archive,
[[T; R]; C]: rkyv::Archive<Archived = [[T::Archived; R]; C]>
)
)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct ArrayStorage<T, const R: usize, const C: usize>(pub [[T; R]; C]);

impl<T, const R: usize, const C: usize> ArrayStorage<T, R, C> {
Expand Down Expand Up @@ -182,6 +178,24 @@ where
}
}

#[cfg(feature = "rkyv-serialize")]
impl<const R: usize, const C: usize> PartialEq<ArrayStorage<f32, R, C>>
for ArrayStorage<rkyv::rend::f32_le, R, C>
{
fn eq(&self, other: &ArrayStorage<f32, R, C>) -> bool {
self.as_slice() == other.as_slice()
}
}

#[cfg(feature = "rkyv-serialize")]
impl<const R: usize, const C: usize> PartialEq<ArrayStorage<rkyv::rend::f32_le, R, C>>
for ArrayStorage<f32, R, C>
{
fn eq(&self, other: &ArrayStorage<rkyv::rend::f32_le, R, C>) -> bool {
self.as_slice() == other.as_slice()
}
}

/*
*
* Serialization.
Expand Down
9 changes: 1 addition & 8 deletions src/base/dimension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use std::fmt::Debug;
use std::ops::{Add, Div, Mul, Sub};
use typenum::{self, Diff, Max, Maximum, Min, Minimum, Prod, Quot, Sum, Unsigned};

#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;
#[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};

Expand All @@ -19,10 +17,6 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(
feature = "rkyv-serialize",
archive_attr(derive(bytecheck::CheckBytes))
)]
pub struct Dyn(pub usize);

#[deprecated(note = "use Dyn instead.")]
Expand Down Expand Up @@ -216,9 +210,8 @@ dim_ops!(
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
archive(as = "Self")
rkyv(derive(Debug), compare(PartialEq))
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct Const<const R: usize>;

/// Trait implemented exclusively by type-level integers.
Expand Down
25 changes: 11 additions & 14 deletions src/base/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ use std::mem;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

#[cfg(feature = "rkyv-serialize-no-std")]
use super::rkyv_wrappers::CustomPhantom;
#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;
#[cfg(feature = "rkyv-serialize-no-std")]
use rkyv::{with::With, Archive, Archived};
use rkyv::Archive;

use simba::scalar::{ClosedAddAssign, ClosedMulAssign, ClosedSubAssign, Field, SupersetOf};
use simba::simd::SimdPartialOrd;
Expand Down Expand Up @@ -161,16 +157,18 @@ pub type MatrixCross<T, R1, C1, R2, C2> =
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(Archive, rkyv::Serialize, rkyv::Deserialize),
Copy link
Contributor Author

@ThierryBerger ThierryBerger Apr 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to derive rkyv::Portable ? I'm not sure what the implications are.

I think this would allow us to avoid a specific ArchivedMatrix being created, which is likely what we want, as was the case with as Matrix.

archive(
as = "Matrix<T::Archived, R, C, S::Archived>",
bound(archive = "
T: Archive,
S: Archive,
With<PhantomData<(T, R, C)>, CustomPhantom<(Archived<T>, R, C)>>: Archive<Archived = PhantomData<(Archived<T>, R, C)>>
")
rkyv(
compare(PartialEq, PartialOrd),
derive(Debug),
archive_bounds(
<S as Archive>::Archived: core::fmt::Debug,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this is a bit constraining ? This is only needed for automated derive (needed for tests)

See https://github.com/dimforge/nalgebra/pull/1502/files#r2025182401

<PhantomData<(T, R, C)> as Archive>::Archived: core::fmt::Debug,
T: PartialEq,
S: Archive,
S: core::fmt::Debug,
)
)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct Matrix<T, R, C, S> {
/// The data storage that contains all the matrix components. Disappointed?
///
Expand Down Expand Up @@ -207,7 +205,6 @@ pub struct Matrix<T, R, C, S> {
// of the `RawStorage` trait. However, because we don't have
// specialization, this is not possible because these `T, R, C`
// allows us to desambiguate a lot of configurations.
#[cfg_attr(feature = "rkyv-serialize-no-std", with(CustomPhantom<(T::Archived, R, C)>))]
_phantoms: PhantomData<(T, R, C)>,
}

Expand Down
11 changes: 3 additions & 8 deletions src/base/rkyv_wrappers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
//! Copied from <https://github.com/rkyv/rkyv_contrib> (MIT-Apache2 licences) which isn’t published yet.

use rkyv::{
rancor::Fallible,
with::{ArchiveWith, DeserializeWith, SerializeWith},
Fallible,
Place,
};
use std::marker::PhantomData;

Expand All @@ -18,13 +19,7 @@ impl<OT: ?Sized, NT: ?Sized> ArchiveWith<PhantomData<OT>> for CustomPhantom<NT>
type Resolver = ();

#[inline]
unsafe fn resolve_with(
_: &PhantomData<OT>,
_: usize,
_: Self::Resolver,
_: *mut Self::Archived,
) {
}
fn resolve_with(_: &PhantomData<OT>, _: Self::Resolver, _: Place<Self::Archived>) {}
}

impl<OT: ?Sized, NT: ?Sized, S: Fallible + ?Sized> SerializeWith<PhantomData<OT>, S>
Expand Down
14 changes: 5 additions & 9 deletions src/base/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ use crate::base::DefaultAllocator;
use crate::storage::RawStorage;
use crate::{Dim, Matrix, OMatrix, RealField, Scalar, SimdComplexField, SimdRealField};

#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;

/// A wrapper that ensures the underlying algebraic entity has a unit norm.
///
/// **It is likely that the only piece of documentation that you need in this page are:**
Expand All @@ -27,14 +24,13 @@ use rkyv::bytecheck;
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
archive(
as = "Unit<T::Archived>",
bound(archive = "
rkyv(derive(Debug)),
rkyv(compare(PartialEq)),
rkyv(archive_bounds(
T: rkyv::Archive,
")
)
<T as rkyv::Archive>::Archived: fmt::Debug,
)),
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct Unit<T> {
pub(crate) value: T,
}
Expand Down
13 changes: 1 addition & 12 deletions src/geometry/dual_quaternion.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// The macros break if the references are taken out, for some reason.
#![allow(clippy::op_ref)]

#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;

use crate::{
Isometry3, Matrix4, Normed, OVector, Point3, Quaternion, Scalar, SimdRealField, Translation3,
Unit, UnitQuaternion, Vector3, Zero, U8,
Expand Down Expand Up @@ -45,16 +42,8 @@ use simba::scalar::{ClosedNeg, RealField};
#[derive(Debug, Copy, Clone)]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
archive(
as = "DualQuaternion<T::Archived>",
bound(archive = "
T: rkyv::Archive,
Quaternion<T>: rkyv::Archive<Archived = Quaternion<T::Archived>>
")
)
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct DualQuaternion<T> {
/// The real component of the quaternion
pub real: Quaternion<T>,
Expand Down
18 changes: 6 additions & 12 deletions src/geometry/isometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ use crate::base::storage::Owned;
use crate::base::{Const, DefaultAllocator, OMatrix, SVector, Scalar, Unit};
use crate::geometry::{AbstractRotation, Point, Translation};

use crate::{Isometry3, Quaternion, Vector3, Vector4};

#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;

/// A direct isometry, i.e., a rotation followed by a translation (aka. a rigid-body motion).
///
/// This is also known as an element of a Special Euclidean (SE) group.
Expand Down Expand Up @@ -71,18 +66,17 @@ use rkyv::bytecheck;
Owned<T, Const<D>>: Deserialize<'de>,
T: Scalar"))
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
archive(
as = "Isometry<T::Archived, R::Archived, D>",
bound(archive = "
rkyv(derive(Debug)),
rkyv(compare(PartialEq)),
rkyv(archive_bounds(
T: rkyv::Archive,
R: rkyv::Archive,
Translation<T, D>: rkyv::Archive<Archived = Translation<T::Archived, D>>
")
)
<R as rkyv::Archive>::Archived: fmt::Debug,
<Translation<T, D> as rkyv::Archive>::Archived: fmt::Debug,
)),
)]
pub struct Isometry<T, R, const D: usize> {
/// The pure rotational part of this isometry.
Expand Down
14 changes: 4 additions & 10 deletions src/geometry/orthographic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,17 @@ use crate::base::{Matrix4, Vector, Vector3};

use crate::geometry::{Point3, Projective3};

#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;

/// A 3D orthographic projection stored as a homogeneous 4x4 matrix.
#[repr(C)]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
archive(
as = "Orthographic3<T::Archived>",
bound(archive = "
T: rkyv::Archive,
Matrix4<T>: rkyv::Archive<Archived = Matrix4<T::Archived>>
")
rkyv(
// This will generate a PartialEq impl between our unarchived
// and archived types
compare(PartialEq),
)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
#[derive(Copy, Clone)]
pub struct Orthographic3<T> {
matrix: Matrix4<T>,
Expand Down
Loading