use std::sync::atomic::{AtomicU64, Ordering}; pub mod color; pub mod colorspace; pub mod containers; pub mod error; pub mod hash; pub mod interval; pub mod math; pub mod mesh; pub mod mipmap; pub mod quaternion; pub mod rng; pub mod sampling; pub mod scattering; pub mod sobol; pub mod splines; pub mod transform; #[inline] pub fn partition_slice(data: &mut [T], predicate: F) -> usize where F: Fn(&T) -> bool, { let mut i = 0; for j in 0..data.len() { if predicate(&data[j]) { data.swap(i, j); i += 1; } } i } #[derive(Debug)] pub struct AtomicFloat { bits: AtomicU64, } impl AtomicFloat { pub fn new(value: f64) -> Self { Self { bits: AtomicU64::new(value.to_bits()), } } pub fn load(&self) -> f64 { f64::from_bits(self.bits.load(Ordering::Relaxed)) } pub fn store(&self, value: f64) { self.bits.store(value.to_bits(), Ordering::Relaxed); } pub fn add(&self, value: f64) { let mut current_bits = self.bits.load(Ordering::Relaxed); loop { let current_val = f64::from_bits(current_bits); let new_val = current_val + value; let new_bits = new_val.to_bits(); match self.bits.compare_exchange_weak( current_bits, new_bits, Ordering::Relaxed, Ordering::Relaxed, ) { Ok(_) => break, Err(x) => current_bits = x, } } } } impl Default for AtomicFloat { fn default() -> Self { Self::new(0.0) } }