Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a point! macro for constructing points #899

Merged
merged 3 commits into from May 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 31 additions & 0 deletions nalgebra-macros/src/lib.rs
Expand Up @@ -280,3 +280,34 @@ pub fn dvector(stream: TokenStream) -> TokenStream {
};
proc_macro::TokenStream::from(output)
}

/// Construct a fixed-size point directly from data.
///
/// **Note: Requires the `macro` feature to be enabled (enabled by default)**.
///
/// Similarly to [`vector!`], this macro facilitates easy construction of points.
///
/// `point!` is intended to be the most readable and performant way of constructing small,
/// points, and it is usable in `const fn` contexts.
///
/// ## Examples
///
/// ```
/// use nalgebra::point;
///
/// // Produces a Point3<_>
/// let v = point![1, 2, 3];
/// ```
#[proc_macro]
pub fn point(stream: TokenStream) -> TokenStream {
let vector = parse_macro_input!(stream as Vector);
let len = vector.len();
let array_tokens = vector.to_array_tokens();
let output = quote! {
nalgebra::Point::<_, #len> {
coords: nalgebra::SVector::<_, #len>
::from_array_storage(nalgebra::ArrayStorage([#array_tokens]))
}
};
proc_macro::TokenStream::from(output)
}
55 changes: 52 additions & 3 deletions nalgebra-macros/tests/tests.rs
@@ -1,9 +1,10 @@
use nalgebra::{
DMatrix, DVector, Matrix1x2, Matrix1x3, Matrix1x4, Matrix2, Matrix2x1, Matrix2x3, Matrix2x4,
Matrix3, Matrix3x1, Matrix3x2, Matrix3x4, Matrix4, Matrix4x1, Matrix4x2, Matrix4x3, SMatrix,
SVector, Vector1, Vector2, Vector3, Vector4, Vector5, Vector6,
Matrix3, Matrix3x1, Matrix3x2, Matrix3x4, Matrix4, Matrix4x1, Matrix4x2, Matrix4x3, Point,
Point1, Point2, Point3, Point4, Point5, Point6, SMatrix, SVector, Vector1, Vector2, Vector3,
Vector4, Vector5, Vector6,
};
use nalgebra_macros::{dmatrix, dvector, matrix, vector};
use nalgebra_macros::{dmatrix, dvector, matrix, point, vector};

fn check_statically_same_type<T>(_: &T, _: &T) {}

Expand Down Expand Up @@ -106,6 +107,19 @@ fn vector_small_dims_exhaustive() {
assert_eq_and_type!(vector![1, 2, 3, 4, 5, 6], Vector6::new(1, 2, 3, 4, 5, 6));
}

// Skip rustfmt because it just makes the test bloated without making it more readable
#[rustfmt::skip]
#[test]
fn point_small_dims_exhaustive() {
assert_eq_and_type!(point![], Point::<i32, 0>::origin());
assert_eq_and_type!(point![1], Point1::<i32>::new(1));
assert_eq_and_type!(point![1, 2], Point2::new(1, 2));
assert_eq_and_type!(point![1, 2, 3], Point3::new(1, 2, 3));
assert_eq_and_type!(point![1, 2, 3, 4], Point4::new(1, 2, 3, 4));
assert_eq_and_type!(point![1, 2, 3, 4, 5], Point5::new(1, 2, 3, 4, 5));
assert_eq_and_type!(point![1, 2, 3, 4, 5, 6], Point6::new(1, 2, 3, 4, 5, 6));
}

#[test]
fn vector_const_fn() {
// Ensure that vector! can be used in const contexts
Expand All @@ -115,6 +129,15 @@ fn vector_const_fn() {
const _: Vector6<i32> = vector![1, 2, 3, 4, 5, 6];
}

#[test]
fn point_const_fn() {
// Ensure that vector! can be used in const contexts
const _: Point<i32, 0> = point![];
const _: Point1<i32> = point![1];
const _: Point2<i32> = point![1, 2];
const _: Point6<i32> = point![1, 2, 3, 4, 5, 6];
}

// Skip rustfmt because it just makes the test bloated without making it more readable
#[rustfmt::skip]
#[test]
Expand Down Expand Up @@ -195,6 +218,23 @@ fn dmatrix_builtin_types() {
let _: DMatrix<f64> = dmatrix![0.0, 1.0; 2.0, 3.0];
}

#[test]
fn point_builtin_types() {
// Check that point! compiles for all built-in types
const _: Point<i8, 4> = point![0, 1, 2, 3];
const _: Point<i16, 4> = point![0, 1, 2, 3];
const _: Point<i32, 4> = point![0, 1, 2, 3];
const _: Point<i64, 4> = point![0, 1, 2, 3];
const _: Point<isize, 4> = point![0, 1, 2, 3];
const _: Point<u8, 4> = point![0, 1, 2, 3];
const _: Point<u16, 4> = point![0, 1, 2, 3];
const _: Point<u32, 4> = point![0, 1, 2, 3];
const _: Point<u64, 4> = point![0, 1, 2, 3];
const _: Point<usize, 4> = point![0, 1, 2, 3];
const _: Point<f32, 4> = point![0.0, 1.0, 2.0, 3.0];
const _: Point<f64, 4> = point![0.0, 1.0, 2.0, 3.0];
}

#[test]
fn dvector_builtin_types() {
// Check that dvector! compiles for all built-in types
Expand Down Expand Up @@ -248,6 +288,15 @@ fn vector_arbitrary_expressions() {
assert_eq_and_type!(a, a_expected);
}

#[rustfmt::skip]
#[test]
fn point_arbitrary_expressions() {
// Test that point! supports arbitrary expressions for its elements
let a = point![1 + 2, 2 * 3, 4 * f(5 + 6), 7 - 8 * 9];
let a_expected = Point4::new(1 + 2, 2 * 3, 4 * f(5 + 6), 7 - 8 * 9);
assert_eq_and_type!(a, a_expected);
}

#[rustfmt::skip]
#[test]
fn dvector_arbitrary_expressions() {
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -137,7 +137,7 @@ pub use crate::sparse::*;
pub use base as core;

#[cfg(feature = "macros")]
pub use nalgebra_macros::{dmatrix, dvector, matrix, vector};
pub use nalgebra_macros::{dmatrix, dvector, matrix, point, vector};

use simba::scalar::SupersetOf;
use std::cmp::{self, Ordering, PartialOrd};
Expand Down
3 changes: 2 additions & 1 deletion tests/core/macros.rs
@@ -1,11 +1,12 @@
use nalgebra::{dmatrix, dvector, matrix, vector};
use nalgebra::{dmatrix, dvector, matrix, point, vector};

#[test]
fn sanity_test() {
// The macros are already tested in `nalgebra-macros`. Here we just test that they compile fine.

let _ = matrix![1, 2, 3; 4, 5, 6];
let _ = dmatrix![1, 2, 3; 4, 5, 6];
let _ = point![1, 2, 3, 4, 5, 6];
let _ = vector![1, 2, 3, 4, 5, 6];
let _ = dvector![1, 2, 3, 4, 5, 6];
}