binius_compute/cpu/
memory.rs

1// Copyright 2025 Irreducible Inc.
2
3use std::{collections::Bound, fmt::Debug, ops::RangeBounds};
4
5use crate::memory::ComputeMemory;
6#[derive(Debug)]
7pub struct CpuMemory;
8
9impl<F: 'static + Sync + Send + Debug> ComputeMemory<F> for CpuMemory {
10	const ALIGNMENT: usize = 1;
11
12	type FSlice<'a> = &'a [F];
13	type FSliceMut<'a> = &'a mut [F];
14
15	fn narrow<'a>(data: &'a &[F]) -> &'a [F] {
16		data
17	}
18
19	fn narrow_mut<'a, 'b: 'a>(data: Self::FSliceMut<'b>) -> Self::FSliceMut<'a> {
20		data
21	}
22
23	fn as_const<'a>(data: &'a &mut [F]) -> &'a [F] {
24		data
25	}
26
27	fn to_const(data: Self::FSliceMut<'_>) -> Self::FSlice<'_> {
28		data
29	}
30
31	fn slice(data: Self::FSlice<'_>, range: impl RangeBounds<usize>) -> Self::FSlice<'_> {
32		let start = match range.start_bound() {
33			Bound::Included(&start) => start,
34			Bound::Excluded(&start) => start + 1,
35			Bound::Unbounded => 0,
36		};
37		let end = match range.end_bound() {
38			Bound::Included(&end) => end + 1,
39			Bound::Excluded(&end) => end,
40			Bound::Unbounded => data.len(),
41		};
42		&data[start..end]
43	}
44
45	fn slice_mut<'a>(data: &'a mut &mut [F], range: impl RangeBounds<usize>) -> &'a mut [F] {
46		let start = match range.start_bound() {
47			Bound::Included(&start) => start,
48			Bound::Excluded(&start) => start + 1,
49			Bound::Unbounded => 0,
50		};
51		let end = match range.end_bound() {
52			Bound::Included(&end) => end + 1,
53			Bound::Excluded(&end) => end,
54			Bound::Unbounded => data.len(),
55		};
56		&mut data[start..end]
57	}
58
59	fn split_at_mut(
60		data: Self::FSliceMut<'_>,
61		mid: usize,
62	) -> (Self::FSliceMut<'_>, Self::FSliceMut<'_>) {
63		data.split_at_mut(mid)
64	}
65
66	fn to_owned_mut<'a>(data: &'a mut &mut [F]) -> &'a mut [F] {
67		data
68	}
69
70	fn slice_chunks_mut<'a>(
71		data: Self::FSliceMut<'a>,
72		chunk_len: usize,
73	) -> impl Iterator<Item = Self::FSliceMut<'a>> {
74		assert_eq!(data.len() % chunk_len, 0, "slice length must be a multiple of chunk_len",);
75
76		data.chunks_exact_mut(chunk_len)
77	}
78}
79
80#[cfg(test)]
81mod tests {
82	use super::*;
83
84	#[test]
85	fn test_try_slice_on_mem_slice() {
86		let data = [4, 5, 6];
87		assert_eq!(CpuMemory::slice(&data, 0..2), &data[0..2]);
88		assert_eq!(CpuMemory::slice(&data, ..2), &data[..2]);
89		assert_eq!(CpuMemory::slice(&data, 1..), &data[1..]);
90		assert_eq!(CpuMemory::slice(&data, ..), &data[..]);
91	}
92
93	#[test]
94	fn test_convert_mut_mem_slice_to_const() {
95		let mut data = [4, 5, 6];
96		let data_clone = data;
97		let data = &mut data[..];
98		let data = CpuMemory::as_const(&data);
99		assert_eq!(data, &data_clone);
100	}
101
102	#[test]
103	fn test_try_slice_on_mut_mem_slice() {
104		let mut data = [4, 5, 6];
105		let mut data_clone = data;
106		let mut data = &mut data[..];
107		assert_eq!(CpuMemory::slice_mut(&mut data, 0..2), &mut data_clone[0..2]);
108		assert_eq!(CpuMemory::slice_mut(&mut data, ..2), &mut data_clone[..2]);
109		assert_eq!(CpuMemory::slice_mut(&mut data, 1..), &mut data_clone[1..]);
110		assert_eq!(CpuMemory::slice_mut(&mut data, ..), &mut data_clone[..]);
111	}
112}