# HG changeset patch # User Tuomo Valkonen # Date 1745803783 18000 # Node ID 1f19c6bbf07b1305db75b5fef0a129bad63ac67e # Parent 123f7f38e16111947fc5d12021ccca7c2258f813 Fix build with stable rust. For optimisations, build.rs now automatically sets a nightly cfg flag, so problems with the nightly feature are avoided. It is still used for required for additional nightly-only features. diff -r 123f7f38e161 -r 1f19c6bbf07b Cargo.lock --- a/Cargo.lock Tue Apr 08 13:30:12 2025 -0500 +++ b/Cargo.lock Sun Apr 27 20:29:43 2025 -0500 @@ -4,7 +4,7 @@ [[package]] name = "alg_tools" -version = "0.3.1" +version = "0.3.2" dependencies = [ "anyhow", "colored", @@ -16,6 +16,7 @@ "num-traits", "numeric_literals", "rayon", + "rustc_version", "serde", "serde_json", "simba", @@ -324,6 +325,15 @@ ] [[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -339,6 +349,12 @@ ] [[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] name = "serde" version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" diff -r 123f7f38e161 -r 1f19c6bbf07b Cargo.toml --- a/Cargo.toml Tue Apr 08 13:30:12 2025 -0500 +++ b/Cargo.toml Sun Apr 27 20:29:43 2025 -0500 @@ -1,6 +1,6 @@ [package] name = "alg_tools" -version = "0.3.1" +version = "0.3.2" edition = "2021" rust-version = "1.85" authors = ["Tuomo Valkonen "] @@ -40,6 +40,11 @@ debug = true [features] -default = ["nightly"] +default = [] use_custom_thread_pool = [] -nightly = [] # enable for higher-performance implementations of some things +# The nightly feature enables some additional features. +# Nightly-based optimisations are decided automatically by build.rs. +nightly = [] + +[build-dependencies] +rustc_version = "0.4" diff -r 123f7f38e161 -r 1f19c6bbf07b build.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build.rs Sun Apr 27 20:29:43 2025 -0500 @@ -0,0 +1,10 @@ +use rustc_version::{version_meta, Channel}; + +fn main() { + // Tell rust that nightly flag exists + println!("cargo::rustc-check-cfg=cfg(nightly)"); + if version_meta().unwrap().channel == Channel::Nightly { + // … and set it for nightly. + println!("cargo:rustc-cfg=nightly"); + } +} diff -r 123f7f38e161 -r 1f19c6bbf07b src/bisection_tree/refine.rs --- a/src/bisection_tree/refine.rs Tue Apr 08 13:30:12 2025 -0500 +++ b/src/bisection_tree/refine.rs Sun Apr 27 20:29:43 2025 -0500 @@ -364,10 +364,10 @@ let mut container = container_arc.lock().unwrap(); // Safe: we just created arg_b and have a mutable exclusive // reference to self containing it. - #[cfg(feature = "nightly")] + #[cfg(nightly)] unsafe { Arc::get_mut_unchecked(arc_b) } .stage_refine(domain, &mut *container); - #[cfg(not(feature = "nightly"))] + #[cfg(not(nightly))] Arc::get_mut(arc_b).unwrap() .stage_refine(domain, &mut *container); diff -r 123f7f38e161 -r 1f19c6bbf07b src/direct_product.rs --- a/src/direct_product.rs Tue Apr 08 13:30:12 2025 -0500 +++ b/src/direct_product.rs Sun Apr 27 20:29:43 2025 -0500 @@ -5,33 +5,38 @@ operations on references. */ -use core::ops::{Mul,MulAssign,Div,DivAssign,Add,AddAssign,Sub,SubAssign,Neg}; -use std::clone::Clone; -use serde::{Serialize, Deserialize}; -use crate::types::{Num, Float}; -use crate::{maybe_lifetime, maybe_ref}; use crate::euclidean::Euclidean; -use crate::instance::{Instance, InstanceMut, Decomposition, DecompositionMut, MyCow}; -use crate::mapping::Space; +use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow}; use crate::linops::AXPY; use crate::loc::Loc; -use crate::norms::{Norm, PairNorm, NormExponent, Normed, HasDual, L2}; +use crate::mapping::Space; +use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; +use crate::types::{Float, Num}; +use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use serde::{Deserialize, Serialize}; +use std::clone::Clone; -#[derive(Debug,Clone,Copy,PartialEq,Eq,Serialize,Deserialize)] -pub struct Pair (pub A, pub B); +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub struct Pair(pub A, pub B); -impl Pair { - pub fn new(a : A, b : B) -> Pair { Pair(a, b) } +impl Pair { + pub fn new(a: A, b: B) -> Pair { + Pair(a, b) + } } -impl From<(A,B)> for Pair { +impl From<(A, B)> for Pair { #[inline] - fn from((a, b) : (A, B)) -> Pair { Pair(a, b) } + fn from((a, b): (A, B)) -> Pair { + Pair(a, b) + } } -impl From> for (A,B) { +impl From> for (A, B) { #[inline] - fn from(Pair(a, b) : Pair) -> (A,B) { (a, b) } + fn from(Pair(a, b): Pair) -> (A, B) { + (a, b) + } } macro_rules! impl_binop { @@ -152,16 +157,18 @@ macro_rules! impl_scalar_assignop { (($a : ty, $b : ty), $field : ty, $trait : ident, $fn : ident) => { - impl<'r> $trait<$field> - for Pair<$a, $b> - where $a: $trait<$field>, $b: $trait<$field> { + impl<'r> $trait<$field> for Pair<$a, $b> + where + $a: $trait<$field>, + $b: $trait<$field>, + { #[inline] - fn $fn(&mut self, a : $field) -> () { + fn $fn(&mut self, a: $field) -> () { self.0.$fn(a); self.1.$fn(a); } } - } + }; } macro_rules! impl_unaryop { @@ -241,24 +248,28 @@ impl Euclidean for Pair where - A : Euclidean, - B : Euclidean, - F : Float, - PairOutput : Euclidean, - Self : Sized - + Mul> + MulAssign - + Div> + DivAssign - + Add> - + Sub> - + for<'b> Add<&'b Self, Output=PairOutput> - + for<'b> Sub<&'b Self, Output=PairOutput> - + AddAssign + for<'b> AddAssign<&'b Self> - + SubAssign + for<'b> SubAssign<&'b Self> - + Neg> + A: Euclidean, + B: Euclidean, + F: Float, + PairOutput: Euclidean, + Self: Sized + + Mul> + + MulAssign + + Div> + + DivAssign + + Add> + + Sub> + + for<'b> Add<&'b Self, Output = PairOutput> + + for<'b> Sub<&'b Self, Output = PairOutput> + + AddAssign + + for<'b> AddAssign<&'b Self> + + SubAssign + + for<'b> SubAssign<&'b Self> + + Neg>, { type Output = PairOutput; - fn dot>(&self, other : I) -> F { + fn dot>(&self, other: I) -> F { let Pair(u, v) = other.decompose(); self.0.dot(u) + self.1.dot(v) } @@ -267,7 +278,7 @@ self.0.norm2_squared() + self.1.norm2_squared() } - fn dist2_squared>(&self, other : I) -> F { + fn dist2_squared>(&self, other: I) -> F { let Pair(u, v) = other.decompose(); self.0.dist2_squared(u) + self.1.dist2_squared(v) } @@ -275,31 +286,30 @@ impl AXPY> for Pair where - U : Space, - V : Space, - A : AXPY, - B : AXPY, - F : Num, - Self : MulAssign, - Pair : MulAssign, - Pair : AXPY>, + U: Space, + V: Space, + A: AXPY, + B: AXPY, + F: Num, + Self: MulAssign, + Pair: MulAssign, + Pair: AXPY>, { - type Owned = Pair; - fn axpy>>(&mut self, α : F, x : I, β : F) { + fn axpy>>(&mut self, α: F, x: I, β: F) { let Pair(u, v) = x.decompose(); self.0.axpy(α, u, β); self.1.axpy(α, v, β); } - fn copy_from>>(&mut self, x : I) { + fn copy_from>>(&mut self, x: I) { let Pair(u, v) = x.decompose(); self.0.copy_from(u); self.1.copy_from(v); } - fn scale_from>>(&mut self, α : F, x : I) { + fn scale_from>>(&mut self, α: F, x: I) { let Pair(u, v) = x.decompose(); self.0.scale_from(α, u); self.1.scale_from(α, v); @@ -321,52 +331,64 @@ #[derive(Copy, Clone, Debug)] pub struct PairDecomposition(D, Q); -impl Space for Pair { +impl Space for Pair { type Decomp = PairDecomposition; } -impl Decomposition> for PairDecomposition +impl Decomposition> for PairDecomposition where - A : Space, - B : Space, - D : Decomposition, - Q : Decomposition, + A: Space, + B: Space, + D: Decomposition, + Q: Decomposition, { - type Decomposition<'b> = Pair, Q::Decomposition<'b>> where Pair : 'b; - type Reference<'b> = Pair, Q::Reference<'b>> where Pair : 'b; + type Decomposition<'b> + = Pair, Q::Decomposition<'b>> + where + Pair: 'b; + type Reference<'b> + = Pair, Q::Reference<'b>> + where + Pair: 'b; #[inline] - fn lift<'b>(Pair(u, v) : Self::Reference<'b>) -> Self::Decomposition<'b> { + fn lift<'b>(Pair(u, v): Self::Reference<'b>) -> Self::Decomposition<'b> { Pair(D::lift(u), Q::lift(v)) } } impl Instance, PairDecomposition> for Pair where - A : Space, - B : Space, - D : Decomposition, - Q : Decomposition, - U : Instance, - V : Instance, + A: Space, + B: Space, + D: Decomposition, + Q: Decomposition, + U: Instance, + V: Instance, { #[inline] - fn decompose<'b>(self) - -> as Decomposition>>::Decomposition<'b> - where Self : 'b, Pair : 'b + fn decompose<'b>( + self, + ) -> as Decomposition>>::Decomposition<'b> + where + Self: 'b, + Pair: 'b, { Pair(self.0.decompose(), self.1.decompose()) } #[inline] - fn ref_instance(&self) - -> as Decomposition>>::Reference<'_> - { + fn ref_instance( + &self, + ) -> as Decomposition>>::Reference<'_> { Pair(self.0.ref_instance(), self.1.ref_instance()) } #[inline] - fn cow<'b>(self) -> MyCow<'b, Pair> where Self : 'b{ + fn cow<'b>(self) -> MyCow<'b, Pair> + where + Self: 'b, + { MyCow::Owned(Pair(self.0.own(), self.1.own())) } @@ -376,35 +398,43 @@ } } - impl<'a, A, B, U, V, D, Q> Instance, PairDecomposition> for &'a Pair where - A : Space, - B : Space, - D : Decomposition, - Q : Decomposition, - U : Instance, - V : Instance, - &'a U : Instance, - &'a V : Instance, + A: Space, + B: Space, + D: Decomposition, + Q: Decomposition, + U: Instance, + V: Instance, + &'a U: Instance, + &'a V: Instance, { #[inline] - fn decompose<'b>(self) - -> as Decomposition>>::Decomposition<'b> - where Self : 'b, Pair : 'b + fn decompose<'b>( + self, + ) -> as Decomposition>>::Decomposition<'b> + where + Self: 'b, + Pair: 'b, { - Pair(D::lift(self.0.ref_instance()), Q::lift(self.1.ref_instance())) + Pair( + D::lift(self.0.ref_instance()), + Q::lift(self.1.ref_instance()), + ) } #[inline] - fn ref_instance(&self) - -> as Decomposition>>::Reference<'_> - { + fn ref_instance( + &self, + ) -> as Decomposition>>::Reference<'_> { Pair(self.0.ref_instance(), self.1.ref_instance()) } #[inline] - fn cow<'b>(self) -> MyCow<'b, Pair> where Self : 'b { + fn cow<'b>(self) -> MyCow<'b, Pair> + where + Self: 'b, + { MyCow::Owned(self.own()) } @@ -413,75 +443,74 @@ let Pair(ref u, ref v) = self; Pair(u.own(), v.own()) } - } -impl DecompositionMut> for PairDecomposition +impl DecompositionMut> for PairDecomposition where - A : Space, - B : Space, - D : DecompositionMut, - Q : DecompositionMut, + A: Space, + B: Space, + D: DecompositionMut, + Q: DecompositionMut, { - type ReferenceMut<'b> = Pair, Q::ReferenceMut<'b>> where Pair : 'b; + type ReferenceMut<'b> + = Pair, Q::ReferenceMut<'b>> + where + Pair: 'b; } impl InstanceMut, PairDecomposition> for Pair where - A : Space, - B : Space, - D : DecompositionMut, - Q : DecompositionMut, - U : InstanceMut, - V : InstanceMut, + A: Space, + B: Space, + D: DecompositionMut, + Q: DecompositionMut, + U: InstanceMut, + V: InstanceMut, { #[inline] - fn ref_instance_mut(&mut self) - -> as DecompositionMut>>::ReferenceMut<'_> - { + fn ref_instance_mut( + &mut self, + ) -> as DecompositionMut>>::ReferenceMut<'_> { Pair(self.0.ref_instance_mut(), self.1.ref_instance_mut()) } } impl<'a, A, B, U, V, D, Q> InstanceMut, PairDecomposition> for &'a mut Pair where - A : Space, - B : Space, - D : DecompositionMut, - Q : DecompositionMut, - U : InstanceMut, - V : InstanceMut, + A: Space, + B: Space, + D: DecompositionMut, + Q: DecompositionMut, + U: InstanceMut, + V: InstanceMut, { #[inline] - fn ref_instance_mut(&mut self) - -> as DecompositionMut>>::ReferenceMut<'_> - { + fn ref_instance_mut( + &mut self, + ) -> as DecompositionMut>>::ReferenceMut<'_> { Pair(self.0.ref_instance_mut(), self.1.ref_instance_mut()) } } - -impl Norm> -for Pair +impl Norm> for Pair where - F : Num, - ExpA : NormExponent, - ExpB : NormExponent, - ExpJ : NormExponent, - A : Norm, - B : Norm, - Loc : Norm, + F: Num, + ExpA: NormExponent, + ExpB: NormExponent, + ExpJ: NormExponent, + A: Norm, + B: Norm, + Loc: Norm, { - fn norm(&self, PairNorm(expa, expb, expj) : PairNorm) -> F { + fn norm(&self, PairNorm(expa, expb, expj): PairNorm) -> F { Loc([self.0.norm(expa), self.1.norm(expb)]).norm(expj) } } - -impl Normed for Pair +impl Normed for Pair where - A : Normed, - B : Normed, + A: Normed, + B: Normed, { type NormExp = PairNorm; @@ -496,11 +525,10 @@ } } -impl HasDual for Pair +impl HasDual for Pair where - A : HasDual, - B : HasDual, - + A: HasDual, + B: HasDual, { type DualSpace = Pair; } diff -r 123f7f38e161 -r 1f19c6bbf07b src/lib.rs --- a/src/lib.rs Tue Apr 08 13:30:12 2025 -0500 +++ b/src/lib.rs Sun Apr 27 20:29:43 2025 -0500 @@ -1,48 +1,54 @@ +// Version of lib.rs for stable builds. + // The main documentation is in the README. #![doc = include_str!("../README.md")] - // We use unicode. We would like to use much more of it than Rust allows. // Live with it. Embrace it. #![allow(uncommon_codepoints)] #![allow(mixed_script_confusables)] #![allow(confusable_idents)] - -#![cfg_attr(feature = "nightly", - feature(maybe_uninit_array_assume_init,maybe_uninit_slice), - feature(float_minimum_maximum), - feature(get_mut_unchecked), - feature(cow_is_borrowed), +// Extra setup for builds with the nightly compiler +#![cfg_attr( + nightly, + feature( + maybe_uninit_array_assume_init, + maybe_uninit_slice, + float_minimum_maximum, + get_mut_unchecked, + cow_is_borrowed + ) )] -pub mod types; -pub mod instance; +#[macro_use] +pub(crate) mod metaprogramming; pub mod collection; -pub mod nanleast; pub mod error; +pub mod euclidean; +pub mod instance; +pub mod maputil; +pub mod nanleast; +pub mod norms; pub mod parallelism; -pub mod maputil; pub mod tuple; -pub mod euclidean; -pub mod norms; +pub mod types; #[macro_use] pub mod loc; +pub mod bisection_tree; +pub mod coefficients; +pub mod convex; +pub mod direct_product; +pub mod discrete_gradient; +pub mod fe_model; pub mod iter; -pub mod linops; pub mod iterate; -pub mod tabledump; -pub mod logger; +pub mod lingrid; +pub mod linops; pub mod linsolve; -pub mod lingrid; -pub mod sets; +pub mod logger; pub mod mapping; -pub mod coefficients; -pub mod fe_model; -pub mod bisection_tree; pub mod nalgebra_support; -pub(crate) mod metaprogramming; -pub mod direct_product; -pub mod convex; -pub mod discrete_gradient; pub mod operator_arithmetic; +pub mod sets; +pub mod tabledump; pub use types::*; diff -r 123f7f38e161 -r 1f19c6bbf07b src/linsolve.rs --- a/src/linsolve.rs Tue Apr 08 13:30:12 2025 -0500 +++ b/src/linsolve.rs Sun Apr 27 20:29:43 2025 -0500 @@ -3,7 +3,7 @@ */ use crate::types::Float; -#[cfg(feature = "nightly")] +#[cfg(nightly)] use std::mem::MaybeUninit; /// Gaussian elimination for $AX=B$, where $A$ and $B$ are both stored in `ab`, @@ -50,7 +50,7 @@ // If the "nightly" feature is enabled, we will use an uninitialised array for a // little bit of efficiency. // This use of MaybeUninit assumes F : Copy. Otherwise undefined behaviour may occur. - #[cfg(feature = "nightly")] + #[cfg(nightly)] { let mut x: [[MaybeUninit; K]; M] = [[const { MaybeUninit::uninit() }; K]; M]; //unsafe { std::mem::MaybeUninit::uninit().assume_init() }; @@ -69,7 +69,7 @@ (&x as *const _ as *const [[F; K]; M]).read() } } - #[cfg(not(feature = "nightly"))] + #[cfg(not(nightly))] { let mut x: [[F; K]; M] = [[F::ZERO; K]; M]; for i in (0..M).rev() { diff -r 123f7f38e161 -r 1f19c6bbf07b src/maputil.rs --- a/src/maputil.rs Tue Apr 08 13:30:12 2025 -0500 +++ b/src/maputil.rs Sun Apr 27 20:29:43 2025 -0500 @@ -3,7 +3,7 @@ */ use itertools::izip; -#[cfg(feature = "nightly")] +#[cfg(nightly)] use std::mem::MaybeUninit; /// Trait for a fixed-length container type. @@ -352,7 +352,7 @@ /// /// If `iter.next()` panicks, all items already yielded by the iterator are /// dropped. -#[cfg(feature = "nightly")] +#[cfg(nightly)] #[inline] pub(crate) fn collect_into_array_unchecked, const N: usize>( mut iter: I, @@ -413,7 +413,7 @@ unreachable!("Something went wrong with iterator length") } -#[cfg(not(feature = "nightly"))] +#[cfg(not(nightly))] #[inline] pub(crate) fn collect_into_array_unchecked, const N: usize>( iter: I, diff -r 123f7f38e161 -r 1f19c6bbf07b src/metaprogramming.rs --- a/src/metaprogramming.rs Tue Apr 08 13:30:12 2025 -0500 +++ b/src/metaprogramming.rs Sun Apr 27 20:29:43 2025 -0500 @@ -9,21 +9,30 @@ /// maybe_ref!(ref, V) // ➡ &V /// maybe_ref!(noref, V) // ➡ V /// ``` -#[macro_export] macro_rules! maybe_ref { - (ref, $x:expr) => { &$x }; - (noref, $x:expr) => { $x }; - (ref, $x:ty) => { &$x }; - (noref, $x:ty) => { $x }; + (ref, $x:expr) => { + &$x + }; + (noref, $x:expr) => { + $x + }; + (ref, $x:ty) => { + &$x + }; + (noref, $x:ty) => { + $x + }; } /// Choose `a` if first argument is the literal `ref`, otherwise `b`. -#[macro_export] -macro_rules! ifref { - (noref, $a:expr, $b:expr) => { $b }; - (ref, $a:expr, $b:expr) => { $a }; -} - +// macro_rules! ifref { +// (noref, $a:expr, $b:expr) => { +// $b +// }; +// (ref, $a:expr, $b:expr) => { +// $a +// }; +// } /// Annotate `x` with a lifetime if the first parameter /// Typically to be used from another macro. @@ -32,10 +41,14 @@ /// maybe_ref!(ref, &'a V) // ➡ &'a V /// maybe_ref!(noref, &'a V) // ➡ V /// ``` -#[macro_export] macro_rules! maybe_lifetime { - (ref, $x:ty) => { $x }; - (noref, &$lt:lifetime $x:ty) => { $x }; - (noref, &$x:ty) => { $x }; + (ref, $x:ty) => { + $x + }; + (noref, &$lt:lifetime $x:ty) => { + $x + }; + (noref, &$x:ty) => { + $x + }; } -