pbrt/src/utils/mod.rs

79 lines
1.6 KiB
Rust

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<T, F>(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)
}
}