pbrt/shared/src/utils/mod.rs

134 lines
2.9 KiB
Rust

use core::sync::atomic::{AtomicU32, AtomicU64, Ordering};
pub mod containers;
pub mod error;
pub mod hash;
pub mod interval;
pub mod math;
pub mod mesh;
pub mod noise;
pub mod ptr;
pub mod quaternion;
pub mod rng;
pub mod sampling;
pub mod sobol;
pub mod splines;
pub mod transform;
pub use ptr::{DevicePtr, Ptr};
pub use transform::{AnimatedTransform, Transform, TransformGeneric};
#[inline]
pub fn find_interval<F>(sz: u32, pred: F) -> u32
where
F: Fn(u32) -> bool,
{
let mut first = 0;
let mut len = sz;
while len > 0 {
let half = len >> 1;
let middle = first + half;
if pred(middle) {
first = middle + 1;
len -= half + 1;
} else {
len = half;
}
}
let ret = (first as i32 - 1).max(0) as u32;
ret.min(sz.saturating_sub(2))
}
#[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
}
pub struct AtomicFloat {
bits: AtomicU32,
}
impl AtomicFloat {
pub fn new(val: f32) -> Self {
Self {
bits: AtomicU32::new(val.to_bits()),
}
}
pub fn get(&self) -> f32 {
f32::from_bits(self.bits.load(Ordering::Relaxed))
}
pub fn set(&self, val: f32) {
self.bits.store(val.to_bits(), Ordering::Relaxed);
}
/// Atomically adds `val` to the current value.
/// Uses a Compare-And-Swap (CAS) loop.
pub fn add(&self, val: f32) {
let mut current_bits = self.bits.load(Ordering::Relaxed);
loop {
let current_val = f32::from_bits(current_bits);
let new_val = current_val + val;
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,
}
}
}
}
pub struct AtomicDouble {
bits: AtomicU64,
}
impl AtomicDouble {
pub fn new(val: f64) -> Self {
Self {
bits: AtomicU64::new(val.to_bits()),
}
}
pub fn get(&self) -> f64 {
f64::from_bits(self.bits.load(Ordering::Relaxed))
}
pub fn add(&self, val: f64) {
let mut current_bits = self.bits.load(Ordering::Relaxed);
loop {
let current_val = f64::from_bits(current_bits);
let new_val = current_val + val;
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,
}
}
}
}