cmm: add color-management module
This commit is contained in:
parent
ed1955d3d1
commit
82085a3858
27 changed files with 1182 additions and 20 deletions
93
src/utils/free_list.rs
Normal file
93
src/utils/free_list.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
40
src/utils/free_list/tests.rs
Normal file
40
src/utils/free_list/tests.rs
Normal 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);
|
||||
}
|
||||
67
src/utils/ordered_float.rs
Normal file
67
src/utils/ordered_float.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue