1
0
Fork 0
forked from wry/wry

cmm: add color-management module

This commit is contained in:
Julian Orth 2025-03-01 13:54:12 +01:00
parent ed1955d3d1
commit 82085a3858
27 changed files with 1182 additions and 20 deletions

93
src/utils/free_list.rs Normal file
View file

@ -0,0 +1,93 @@
#[cfg(test)]
mod tests;
use {
crate::utils::ptr_ext::MutPtrExt,
std::{
array,
cell::UnsafeCell,
fmt::{Debug, Formatter},
marker::PhantomData,
},
};
type Seg = usize;
const SEG_SIZE: usize = size_of::<Seg>() * 8;
pub struct FreeList<T, const N: usize> {
levels: UnsafeCell<[Vec<Seg>; N]>,
_phantom: PhantomData<T>,
}
impl<T, const N: usize> Default for FreeList<T, N> {
fn default() -> Self {
Self {
levels: UnsafeCell::new(array::from_fn(|_| Vec::new())),
_phantom: Default::default(),
}
}
}
impl<T, const N: usize> Debug for FreeList<T, N> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FreeList")
.field("levels", self.get())
.finish()
}
}
impl<T, const N: usize> FreeList<T, N> {
fn get(&self) -> &mut [Vec<Seg>; N] {
unsafe { self.levels.get().deref_mut() }
}
pub fn release(&self, n: T)
where
T: Into<u32>,
{
let mut ext = n.into() as usize;
let mut int;
let levels = self.get();
assert!(ext / SEG_SIZE < levels[0].len());
for level in self.get() {
int = ext % SEG_SIZE;
ext /= SEG_SIZE;
unsafe {
*level.get_unchecked_mut(ext) |= 1 << int;
}
}
}
pub fn acquire(&self) -> T
where
u32: Into<T>,
{
let mut ext = 'last: {
let level = &mut self.get()[N - 1];
for (idx, &seg) in level.iter().enumerate() {
if seg != 0 {
break 'last idx;
}
}
level.len()
};
for level in self.get().iter_mut().rev() {
if ext == level.len() {
level.push(!0);
}
let seg = unsafe { level.get_unchecked(ext) };
ext = SEG_SIZE * ext + seg.trailing_zeros() as usize;
}
let id = ext as u32;
for level in self.get().iter_mut() {
let int = ext % SEG_SIZE;
ext /= SEG_SIZE;
let seg = unsafe { level.get_unchecked_mut(ext) };
*seg &= !(1 << int);
if *seg != 0 {
break;
}
}
id.into()
}
}

View file

@ -0,0 +1,40 @@
use crate::utils::free_list::FreeList;
#[test]
fn test() {
let list = FreeList::<u32, 3>::default();
for i in 0..4097 {
assert_eq!(list.acquire(), i);
}
list.release(100);
assert_eq!(list.acquire(), 100);
assert_eq!(list.acquire(), 4097);
for i in 1..22 {
list.release(i);
}
for i in 1..22 {
assert_eq!(list.acquire(), i);
}
assert_eq!(list.acquire(), 4098);
for i in 64..128 {
list.release(i);
}
for i in 64..128 {
assert_eq!(list.acquire(), i);
}
assert_eq!(list.acquire(), 4099);
for i in 0..4100 {
list.release(i);
}
for i in 0..4101 {
assert_eq!(list.acquire(), i);
}
}
#[test]
#[should_panic]
fn release_out_of_bounds() {
let list = FreeList::<u32, 3>::default();
list.acquire();
list.release(500);
}

View file

@ -0,0 +1,67 @@
use std::{
fmt::{Debug, Display, Formatter},
hash::{Hash, Hasher},
ops::{Add, Div, Mul, Sub},
};
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct F64(pub f64);
impl Eq for F64 {}
impl PartialEq for F64 {
fn eq(&self, other: &Self) -> bool {
self.0.to_bits() == other.0.to_bits()
}
}
impl Hash for F64 {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.to_bits().hash(state);
}
}
impl Add<F64> for F64 {
type Output = Self;
fn add(self, rhs: F64) -> Self::Output {
Self(self.0 + rhs.0)
}
}
impl Sub<F64> for F64 {
type Output = Self;
fn sub(self, rhs: F64) -> Self::Output {
Self(self.0 - rhs.0)
}
}
impl Mul<F64> for F64 {
type Output = Self;
fn mul(self, rhs: F64) -> Self::Output {
Self(self.0 * rhs.0)
}
}
impl Div<F64> for F64 {
type Output = Self;
fn div(self, rhs: F64) -> Self::Output {
Self(self.0 / rhs.0)
}
}
impl Display for F64 {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.0, f)
}
}
impl Debug for F64 {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.0, f)
}
}