1use crate::error::{Error, Kind};
3use num_complex::{Complex32, Complex64};
4use std::borrow::Cow;
5
6macro_rules! buffers {
8 ($owned:ident, $view:ident, $tag:ident, $outer:ident, $kind:ident, $widest:ty: $($variant:ident($t:ty = $fill:expr)),+) => {
9 #[derive(Clone, Debug)]
10 pub enum $owned { $($variant(Vec<$t>)),+ }
11 #[derive(Clone, Copy, Debug)]
12 pub enum $view<'a> { $($variant(&'a [$t])),+ }
13 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
14 pub enum $tag { $($variant),+ }
15 impl $owned {
16 pub fn with_capacity(tag: $tag, capacity: usize) -> Self { match tag { $($tag::$variant => Self::$variant(Vec::with_capacity(capacity))),+ } }
17 #[inline]
18 pub fn view(&self) -> $view<'_> { match self { $(Self::$variant(v) => $view::$variant(v)),+ } }
19 #[inline]
20 pub fn capacity(&self) -> usize { match self { $(Self::$variant(v) => v.capacity()),+ } }
21 #[inline]
22 pub fn as_mut_ptr(&mut self) -> *mut u8 { match self { $(Self::$variant(v) => v.as_mut_ptr().cast()),+ } }
23 #[inline]
28 pub unsafe fn set_len(&mut self, n: usize) { match self { $(Self::$variant(v) => unsafe { v.set_len(n) }),+ } }
29 pub fn extend_from(&mut self, source: $view<'_>, range: std::ops::Range<usize>) -> bool {
31 match (self, source) {
32 $((Self::$variant(d), $view::$variant(s)) => d.extend_from_slice(&s[range]),)+
33 #[allow(unreachable_patterns)]
34 _ => return false,
35 }
36 true
37 }
38 }
39 impl $view<'_> {
40 #[inline]
41 pub fn len(self) -> usize { match self { $(Self::$variant(v) => v.len()),+ } }
42 #[inline]
43 pub fn is_empty(self) -> bool { self.len() == 0 }
44 #[inline]
45 pub fn as_ptr(self) -> *const u8 { match self { $(Self::$variant(v) => v.as_ptr().cast()),+ } }
46 #[inline]
47 pub fn tag(self) -> $tag { match self { $(Self::$variant(_) => $tag::$variant),+ } }
48 }
49 impl<'a> $view<'a> {
50 pub fn widened(self) -> Cow<'a, [$widest]> {
52 match self { $(Self::$variant(v) => Source::<$widest>::borrowed(v).map_or_else(|| Cow::Owned(read_all(v)), Cow::Borrowed)),+ }
53 }
54 }
55 impl PartialEq for $view<'_> {
57 fn eq(&self, other: &Self) -> bool {
58 match (*self, *other) { $((Self::$variant(x), Self::$variant(y)) => x == y,)+ (x, y) => x.widened() == y.widened() }
59 }
60 }
61 $(impl Element for $t {
62 const FILL: Self = $fill;
63 const DTYPE: DType = DType::$kind($tag::$variant);
64 #[inline]
65 fn of(view: View<'_>) -> Option<&[Self]> { match view { View::$outer($view::$variant(v)) => Some(v), _ => None } }
66 #[inline]
67 fn of_mut(buffer: &mut Buffer) -> Option<&mut [Self]> { match buffer { Buffer::$outer($owned::$variant(v)) => Some(v), _ => None } }
68 #[inline]
69 fn view(items: &[Self]) -> View<'_> { View::$outer($view::$variant(items)) }
70 #[inline]
71 fn buffer(data: Vec<Self>) -> Buffer { Buffer::$outer($owned::$variant(data)) }
72 #[inline]
73 fn vec(buffer: Buffer) -> Option<Vec<Self>> { match buffer { Buffer::$outer($owned::$variant(v)) => Some(v), _ => None } }
74 #[inline]
75 fn vec_mut(buffer: &mut Buffer) -> Option<&mut Vec<Self>> { match buffer { Buffer::$outer($owned::$variant(v)) => Some(v), _ => None } }
76 #[inline]
77 fn truth(b: bool) -> Self { Source::<Self>::read(b) }
78 })+
79 };
80}
81buffers!(IntBuf, Ints, Width, Integers, Integer, i64: U8(u8 = 0), I16(i16 = 0), I32(i32 = 0), I64(i64 = 0));
82buffers!(FloatBuf, Floats, FloatWidth, Floats, Float, f64: F16(half::f16 = half::f16::ZERO), F32(f32 = 0.0), F64(f64 = 0.0));
84buffers!(ComplexBuf, Complexes, ComplexWidth, Complexes, Complex, Complex64: F32(Complex32 = Complex32::new(0.0, 0.0)), F64(Complex64 = Complex64::new(0.0, 0.0)));
86macro_rules! single {
88 ($($t:ty: $variant:ident($dtype:ident) = $fill:expr, $truth:expr),+) => {$(
89 impl Element for $t {
90 const FILL: Self = $fill;
91 const DTYPE: DType = DType::$dtype;
92 #[inline]
93 fn of(view: View<'_>) -> Option<&[Self]> { match view { View::$variant(v) => Some(v), _ => None } }
94 #[inline]
95 fn of_mut(buffer: &mut Buffer) -> Option<&mut [Self]> { match buffer { Buffer::$variant(v) => Some(v), _ => None } }
96 #[inline]
97 fn view(items: &[Self]) -> View<'_> { View::$variant(items) }
98 #[inline]
99 fn buffer(data: Vec<Self>) -> Buffer { Buffer::$variant(data) }
100 #[inline]
101 fn vec(buffer: Buffer) -> Option<Vec<Self>> { match buffer { Buffer::$variant(v) => Some(v), _ => None } }
102 #[inline]
103 fn vec_mut(buffer: &mut Buffer) -> Option<&mut Vec<Self>> { match buffer { Buffer::$variant(v) => Some(v), _ => None } }
104 #[inline]
105 fn truth(b: bool) -> Self { ($truth)(b) }
106 }
107 )+};
108}
109single!(bool: Booleans(Boolean) = false, |b| b, char: Characters(Character) = ' ', |b| if b { '\u{1}' } else { '\0' });
110
111impl From<FloatWidth> for ComplexWidth {
113 fn from(width: FloatWidth) -> Self { match width { FloatWidth::F64 => Self::F64, FloatWidth::F16 | FloatWidth::F32 => Self::F32 } }
114}
115impl From<ComplexWidth> for FloatWidth {
116 fn from(width: ComplexWidth) -> Self { match width { ComplexWidth::F32 => Self::F32, ComplexWidth::F64 => Self::F64 } }
117}
118
119macro_rules! width_macros {
121 ($d:tt $values:ident: $slices:ident, $types:ident: $widths:ident { $($skip:ident => [$($st:tt)+]),* ; $($kept:ident => [$($kt:tt)+]),+ }) => {
122 #[macro_export]
123 macro_rules! $values {
124 (kernel $d v:expr, |$d x:ident| $d body:expr) => {
125 match $d v {
126 $($crate::buffer::$slices::$skip(_) => None,)*
127 $($crate::buffer::$slices::$kept($d x) => $d body,)+
128 }
129 };
130 ($d v:expr, |$d x:ident| $d body:expr) => {
131 match $d v {
132 $($crate::buffer::$slices::$skip($d x) => $d body,)*
133 $($crate::buffer::$slices::$kept($d x) => $d body,)+
134 }
135 };
136 }
137 #[macro_export]
138 macro_rules! $types {
139 (kernel $d w:expr, $d t:ident => $d body:expr) => {
140 match $d w {
141 $($crate::buffer::$widths::$skip => None,)*
142 $($crate::buffer::$widths::$kept => { type $d t = $($kt)+; $d body })+
143 }
144 };
145 ($d w:expr, $d t:ident => $d body:expr) => {
146 match $d w {
147 $($crate::buffer::$widths::$skip => { type $d t = $($st)+; $d body })*
148 $($crate::buffer::$widths::$kept => { type $d t = $($kt)+; $d body })+
149 }
150 };
151 }
152 };
153}
154width_macros!($ with_ints: Ints, with_width: Width { ; U8 => [u8], I16 => [i16], I32 => [i32], I64 => [i64] });
155width_macros!($ with_floats: Floats, with_float_width: FloatWidth { F16 => [$ crate::half::f16]; F32 => [f32], F64 => [f64] });
156width_macros!($ with_complexes: Complexes, with_complex_width: ComplexWidth { ; F32 => [$ crate::num_complex::Complex32], F64 => [$ crate::num_complex::Complex64] });
157
158#[macro_export]
160macro_rules! with_inexact {
161 ($dtype:expr, $t:ident => $body:expr) => {
162 match $dtype {
163 $crate::buffer::DType::Float($crate::buffer::FloatWidth::F32) => { type $t = f32; $body }
164 $crate::buffer::DType::Float($crate::buffer::FloatWidth::F64) => { type $t = f64; $body }
165 $crate::buffer::DType::Complex($crate::buffer::ComplexWidth::F32) => { type $t = $crate::num_complex::Complex32; $body }
166 $crate::buffer::DType::Complex($crate::buffer::ComplexWidth::F64) => { type $t = $crate::num_complex::Complex64; $body }
167 _ => panic!("with_inexact! takes a computing dtype that DType::inexact gives"),
168 }
169 };
170}
171
172#[macro_export]
174macro_rules! with_int_pair {
175 ($a:expr, $b:expr, |$x:ident, $y:ident| $body:expr) => {
176 match ($a, $b) {
177 ($crate::buffer::Ints::U8($x), $crate::buffer::Ints::U8($y)) => $body,
178 ($crate::buffer::Ints::I16($x), $crate::buffer::Ints::I16($y)) => $body,
179 ($crate::buffer::Ints::I32($x), $crate::buffer::Ints::I32($y)) => $body,
180 (a, b) => {
181 let (a, b) = (a.widened(), b.widened());
182 let ($x, $y) = (&*a, &*b);
183 $body
184 }
185 }
186 };
187}
188
189impl Width {
190 #[inline]
192 fn bytes(self) -> usize { with_width!(self, T => std::mem::size_of::<T>()) }
193 #[inline]
194 pub fn holds(self, n: i64) -> bool { with_width!(self, T => T::try_from(n).is_ok()) }
195 #[inline]
197 pub fn narrowest<T: Into<i64>>(min: T, max: T) -> Self {
198 let (min, max) = (min.into(), max.into());
199 for w in [Self::U8, Self::I16, Self::I32] { if min > max || w.holds(min) && w.holds(max) { return w; } }
200 Self::I64
201 }
202 #[inline]
204 pub fn below(bound: usize) -> Self { Self::narrowest(0, bound as i64 - 1) }
205 #[inline]
207 pub fn join(self, other: Self) -> Self { if self.bytes() >= other.bytes() { self } else { other } }
208 #[inline]
210 pub fn wider(self) -> Option<Self> {
211 match self { Self::U8 => Some(Self::I16), Self::I16 => Some(Self::I32), Self::I32 => Some(Self::I64), Self::I64 => None }
212 }
213 #[inline]
215 pub fn float(self, limit: FloatWidth) -> FloatWidth {
216 (match self { Self::U8 => FloatWidth::F16, Self::I16 => FloatWidth::F32, Self::I32 | Self::I64 => FloatWidth::F64 }).min(limit)
217 }
218}
219
220impl FloatWidth {
221 pub fn epsilon(self) -> f64 { with_float_width!(self, F => <F as num_traits::Float>::epsilon().into()) }
223 pub fn bits(self) -> i64 { with_float_width!(self, F => 8 * std::mem::size_of::<F>() as i64) }
225 pub fn of_bits(bits: i64) -> Option<Self> { match bits { 16 => Some(Self::F16), 32 => Some(Self::F32), 64 => Some(Self::F64), _ => None } }
227}
228
229impl<'a> Ints<'a> {
230 #[inline]
232 pub fn get(self, i: usize) -> i64 { with_ints!(self, |x| x[i].into()) }
233}
234
235impl<'a> Floats<'a> {
236 #[inline]
238 pub fn get(self, i: usize) -> f64 { with_floats!(self, |v| v[i].into()) }
239}
240
241impl<'a> Complexes<'a> {
242 #[inline]
244 pub fn get(self, i: usize) -> Complex64 { with_complexes!(self, |v| Source::<Complex64>::read(v[i])) }
245}
246impl FloatBuf {
247 pub fn collect(width: FloatWidth, values: impl Iterator<Item = f64>) -> Self {
249 match width {
250 FloatWidth::F16 => Self::F16(values.map(Source::read).collect()), FloatWidth::F32 => Self::F32(values.map(Source::read).collect()),
251 FloatWidth::F64 => Self::F64(values.collect())
252 }
253 }
254}
255
256impl ComplexBuf {
257 pub fn collect(width: ComplexWidth, values: impl Iterator<Item = Complex64>) -> Self {
259 match width { ComplexWidth::F32 => Self::F32(values.map(Source::read).collect()), ComplexWidth::F64 => Self::F64(values.collect()) }
260 }
261}
262
263#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
265pub enum DType { Boolean, Integer(Width), Float(FloatWidth), Complex(ComplexWidth), Character }
266
267impl DType {
268 #[inline]
270 pub fn is_integral(self) -> bool { matches!(self, Self::Boolean | Self::Integer(_)) }
271 #[inline]
273 pub fn mathish(self) -> bool { matches!(self, Self::Float(FloatWidth::F64) | Self::Complex(ComplexWidth::F64)) }
274 #[inline]
276 pub fn is_real(self) -> bool { matches!(self, Self::Boolean | Self::Integer(_) | Self::Float(_)) }
277 pub fn kind(self) -> u8 {
279 match self { Self::Boolean => 0, Self::Integer(_) => 1, Self::Float(_) => 2, Self::Complex(_) => 3, Self::Character => 4 }
280 }
281 pub fn name(self) -> &'static str {
283 match self {
284 Self::Boolean => "bool", Self::Integer(Width::U8) => "uint8", Self::Integer(Width::I16) => "int16", Self::Integer(Width::I32) => "int32",
285 Self::Integer(Width::I64) => "int64", Self::Float(FloatWidth::F16) => "float16", Self::Float(FloatWidth::F32) => "float32",
286 Self::Float(FloatWidth::F64) => "float64", Self::Complex(ComplexWidth::F32) => "complex64", Self::Complex(ComplexWidth::F64) => "complex128",
287 Self::Character => "character"
288 }
289 }
290 pub fn named(name: &str) -> Option<Self> { Self::ALL.into_iter().find(|d| d.name() == name) }
292 pub fn widens_to(self, to: DType) -> bool { self.common(to) == Some(to) }
294 pub fn inexact(self, limit: FloatWidth) -> Option<(DType, DType)> {
296 let at_least_f32 = |w: FloatWidth| { let f = Self::Float(w.max(FloatWidth::F32)); (f, f) };
297 Some(match self {
298 Self::Boolean => at_least_f32(FloatWidth::F16), Self::Integer(w) => at_least_f32(w.float(limit)),
299 Self::Float(FloatWidth::F16) => (Self::Float(FloatWidth::F32), self), Self::Float(_) | Self::Complex(_) => (self, self),
300 Self::Character => return None
301 })
302 }
303 pub fn numpy_float(self) -> FloatWidth { match self.inexact(FloatWidth::F64) { Some((DType::Float(w), _)) => w, _ => FloatWidth::F64 } }
305
306 pub fn computes_in(self, int: Width, float: FloatWidth, has: impl Fn(DType) -> bool) -> Option<DType> {
308 if has(self) { return Some(self); }
309 let (integer, float, whole) = match self {
310 Self::Boolean => (Some(Self::Integer(int)), Self::Float(float), None),
311 Self::Integer(w) => (Some(Self::Integer(w.join(int))), Self::Float(float), None),
312 Self::Float(_) => (None, self.inexact(float)?.0, Some(Self::Integer(int))), _ => (None, self.inexact(float)?.0, None)
313 };
314 integer.into_iter().chain(Self::ALL.into_iter().filter(|&d| float.widens_to(d))).chain(whole).find(|&d| has(d))
315 }
316 pub fn common(self, other: DType) -> Option<DType> {
318 use DType::*;
319 let (low, high) = if self.kind() <= other.kind() { (self, other) } else { (other, self) };
320 Some(match (low, high) {
321 (Character, Character) => Character, (_, Character) => return None, (Boolean, d) | (Integer(_), d @ (Float(_) | Complex(_))) => d,
322 (Integer(a), Integer(b)) => Integer(a.join(b)), (Float(a), Float(b)) => Float(a.max(b)), (Float(f), Complex(c)) => Complex(c.max(f.into())),
323 (Complex(a), Complex(b)) => Complex(a.max(b)), _ => unreachable!("the pair is ordered by kind")
324 })
325 }
326 pub fn common_weak(self, weak: DType) -> Option<DType> {
328 use DType::*;
329 Some(match (self, weak) {
330 (Character, Character) => Character, (Character, _) | (_, Character) => return None, (Float(_) | Complex(_), Complex(_)) => self.complex(),
331 _ if weak.kind() > self.kind() => weak, _ => self
332 })
333 }
334 pub fn real(self) -> DType {
336 match self {
337 Self::Complex(ComplexWidth::F32) => Self::Float(FloatWidth::F32), Self::Complex(ComplexWidth::F64) => Self::Float(FloatWidth::F64), d => d
338 }
339 }
340 pub fn complex(self) -> DType {
342 Self::Complex(match self {
343 Self::Float(FloatWidth::F16 | FloatWidth::F32) | Self::Complex(ComplexWidth::F32) => ComplexWidth::F32, _ => ComplexWidth::F64
344 })
345 }
346}
347
348#[doc(hidden)]
350#[macro_export]
351macro_rules! element_types {
352 (($($callback:tt)+) $($args:tt)*) => {
353 $($callback)+! {$($args)* [
354 Boolean: ($crate::buffer::DType::Boolean) bool, U8: ($crate::buffer::DType::Integer($crate::buffer::Width::U8)) u8,
355 I16: ($crate::buffer::DType::Integer($crate::buffer::Width::I16)) i16, I32: ($crate::buffer::DType::Integer($crate::buffer::Width::I32)) i32,
356 I64: ($crate::buffer::DType::Integer($crate::buffer::Width::I64)) i64,
357 F16: ($crate::buffer::DType::Float($crate::buffer::FloatWidth::F16)) $crate::half::f16,
358 F32: ($crate::buffer::DType::Float($crate::buffer::FloatWidth::F32)) f32, F64: ($crate::buffer::DType::Float($crate::buffer::FloatWidth::F64)) f64,
359 C32: ($crate::buffer::DType::Complex($crate::buffer::ComplexWidth::F32)) $crate::num_complex::Complex32,
360 C64: ($crate::buffer::DType::Complex($crate::buffer::ComplexWidth::F64)) $crate::num_complex::Complex64,
361 Character: ($crate::buffer::DType::Character) char
362 ]}
363 };
364}
365
366macro_rules! dtypes {
368 ([$($name:ident: ($($d:tt)+) $t:ty),+]) => {
369 impl DType {
370 pub const ALL: [DType; [$(stringify!($name)),+].len()] = [$($($d)+),+];
372 #[inline]
374 pub const fn index(self) -> usize {
375 enum Position { $($name),+ }
376 match self { $($($d)+ => Position::$name as usize),+ }
377 }
378 }
379 };
380}
381element_types!((dtypes));
382
383macro_rules! dtype_macro {
385 ($d:tt [$($name:ident: ($($dtype:tt)+) $t:ty),+]) => {
386 #[macro_export]
388 macro_rules! with_dtype {
389 ($d dtype:expr, $d t:ident => $d body:expr) => {
390 match $d dtype { $($($dtype)+ => { type $d t = $t; $d body }),+ }
391 };
392 }
393 };
394}
395element_types!((dtype_macro) $);
396
397impl DType {
398 pub fn bytes(self) -> usize { with_dtype!(self, T => std::mem::size_of::<T>()) }
400}
401
402#[derive(Clone, Debug)]
404pub enum Buffer { Booleans(Vec<bool>), Integers(IntBuf), Floats(FloatBuf), Complexes(ComplexBuf), Characters(Vec<char>) }
405
406#[derive(Clone, Copy, Debug)]
408pub enum View<'a> { Booleans(&'a [bool]), Integers(Ints<'a>), Floats(Floats<'a>), Complexes(Complexes<'a>), Characters(&'a [char]) }
409
410pub enum Items<'a> { Borrowed(View<'a>), Owned(Buffer) }
412
413impl<'a> Items<'a> {
414 pub fn view(&self) -> View<'_> { match self { Self::Borrowed(v) => *v, Self::Owned(b) => b.view() } }
415 pub fn of<T: Element>(&self) -> &[T] { T::of(self.view()).expect("items at their own element type") }
416 pub fn items<T: Element>(self) -> Cow<'a, [T]> {
418 match self {
419 Self::Borrowed(v) => Cow::Borrowed(T::of(v).expect("items at their own element type")),
420 Self::Owned(b) => Cow::Owned(T::vec(b).expect("items at their own element type")),
421 }
422 }
423}
424
425impl Buffer {
426 pub fn with_capacity(dtype: DType, capacity: usize) -> Self {
428 match dtype {
429 DType::Boolean => Self::Booleans(Vec::with_capacity(capacity)), DType::Integer(width) => Self::Integers(IntBuf::with_capacity(width, capacity)),
430 DType::Float(width) => Self::Floats(FloatBuf::with_capacity(width, capacity)),
431 DType::Complex(width) => Self::Complexes(ComplexBuf::with_capacity(width, capacity)),
432 DType::Character => Self::Characters(Vec::with_capacity(capacity))
433 }
434 }
435 #[inline]
436 pub fn view(&self) -> View<'_> {
437 match self {
438 Self::Booleans(v) => View::Booleans(v), Self::Integers(v) => View::Integers(v.view()), Self::Floats(v) => View::Floats(v.view()),
439 Self::Complexes(v) => View::Complexes(v.view()), Self::Characters(v) => View::Characters(v)
440 }
441 }
442 #[inline]
443 pub fn len(&self) -> usize { self.view().len() }
444 #[inline]
445 pub fn is_empty(&self) -> bool { self.len() == 0 }
446 #[inline]
447 pub fn dtype(&self) -> DType { self.view().dtype() }
448 pub fn capacity(&self) -> usize {
449 match self {
450 Self::Booleans(v) => v.capacity(), Self::Integers(v) => v.capacity(), Self::Floats(v) => v.capacity(), Self::Complexes(v) => v.capacity(),
451 Self::Characters(v) => v.capacity()
452 }
453 }
454 pub fn reserve(&mut self, additional: usize) { with_dtype!(self.dtype(), T => T::vec_mut(self).expect("the buffer has its dtype").reserve(additional)) }
456 pub fn as_mut_ptr(&mut self) -> *mut u8 {
458 match self {
459 Self::Booleans(v) => v.as_mut_ptr().cast(), Self::Integers(v) => v.as_mut_ptr(), Self::Floats(v) => v.as_mut_ptr(),
460 Self::Complexes(v) => v.as_mut_ptr(), Self::Characters(v) => v.as_mut_ptr().cast()
461 }
462 }
463 pub fn extend_from(&mut self, source: View<'_>, range: std::ops::Range<usize>) -> bool {
465 match (self, source) {
466 (Self::Booleans(d), View::Booleans(s)) => d.extend_from_slice(&s[range]), (Self::Integers(d), View::Integers(s)) => return d.extend_from(s, range),
467 (Self::Floats(d), View::Floats(s)) => return d.extend_from(s, range), (Self::Complexes(d), View::Complexes(s)) => return d.extend_from(s, range),
468 (Self::Characters(d), View::Characters(s)) => d.extend_from_slice(&s[range]), _ => return false
469 }
470 true
471 }
472 pub unsafe fn set_len(&mut self, n: usize) {
477 match self {
478 Self::Booleans(v) => unsafe { v.set_len(n) }, Self::Integers(v) => unsafe { v.set_len(n) }, Self::Floats(v) => unsafe { v.set_len(n) },
479 Self::Complexes(v) => unsafe { v.set_len(n) }, Self::Characters(v) => unsafe { v.set_len(n) }
480 }
481 }
482 pub fn clear(&mut self) {
484 unsafe { self.set_len(0) }
486 }
487}
488
489#[derive(Clone, Debug)]
491pub struct Fill(Buffer);
492
493impl Fill {
494 pub fn new(value: View<'_>, dtype: DType) -> Result<Self, Error> {
496 if value.len() != 1 { return Err(Error::new(Kind::Length, "a fill must contain one item")); }
497 Buffer::kept(value, dtype).map(Self)
498 }
499 pub fn view(&self) -> View<'_> { self.0.view() }
500 pub fn cast(&self, dtype: DType) -> Result<Self, Error> { Buffer::cast(self.view(), dtype).map(Self) }
502 #[inline]
504 pub fn item<A: Element>(fill: Option<&std::sync::Arc<Self>>) -> A { fill.map_or(A::FILL, |f| A::of(f.view()).expect("a fill has its source's dtype")[0]) }
505}
506impl PartialEq for Fill { fn eq(&self, other: &Self) -> bool { self.view().identical(other.view()) } }
507impl Eq for Fill {}
508impl PartialEq for Buffer { fn eq(&self, other: &Self) -> bool { self.view() == other.view() } }
510
511impl<'a> View<'a> {
512 #[inline]
514 pub fn slice(self, range: std::ops::Range<usize>) -> Self { with_dtype!(self.dtype(), T => T::view(&T::of(self).expect("the view has its dtype")[range])) }
515 #[inline]
516 pub fn len(self) -> usize {
517 match self {
518 Self::Booleans(v) => v.len(), Self::Integers(v) => v.len(), Self::Floats(v) => v.len(), Self::Complexes(v) => v.len(),
519 Self::Characters(v) => v.len()
520 }
521 }
522 #[inline]
523 pub fn is_empty(self) -> bool { self.len() == 0 }
524 #[inline]
525 pub fn as_ptr(self) -> *const u8 {
526 match self {
527 Self::Booleans(v) => v.as_ptr().cast(), Self::Integers(v) => v.as_ptr(), Self::Floats(v) => v.as_ptr(), Self::Complexes(v) => v.as_ptr(),
528 Self::Characters(v) => v.as_ptr().cast()
529 }
530 }
531 #[inline]
532 pub fn dtype(self) -> DType {
533 match self {
534 Self::Booleans(_) => DType::Boolean, Self::Integers(v) => DType::Integer(v.tag()), Self::Floats(v) => DType::Float(v.tag()),
535 Self::Complexes(v) => DType::Complex(v.tag()), Self::Characters(_) => DType::Character
536 }
537 }
538 pub fn identical(self, other: View<'_>) -> bool {
540 let bytes = |v: View<'_>| unsafe { std::slice::from_raw_parts(v.as_ptr(), v.len() * v.dtype().bytes()) };
542 self.dtype() == other.dtype() && bytes(self) == bytes(other)
543 }
544}
545impl PartialEq for View<'_> {
546 fn eq(&self, other: &Self) -> bool {
547 match (*self, *other) {
548 (Self::Booleans(x), Self::Booleans(y)) => x == y, (Self::Integers(x), Self::Integers(y)) => x == y, (Self::Floats(x), Self::Floats(y)) => x == y,
549 (Self::Complexes(x), Self::Complexes(y)) => x == y, (Self::Characters(x), Self::Characters(y)) => x == y, _ => false
550 }
551 }
552}
553
554pub trait Element: Copy + Send + Sync + 'static + crate::gather::Item {
556 const FILL: Self;
558 const DTYPE: DType;
560 fn of(view: View<'_>) -> Option<&[Self]>;
562 fn of_mut(buffer: &mut Buffer) -> Option<&mut [Self]>;
564 fn view(items: &[Self]) -> View<'_>;
566 fn buffer(data: Vec<Self>) -> Buffer;
568 fn vec(buffer: Buffer) -> Option<Vec<Self>>;
570 fn vec_mut(buffer: &mut Buffer) -> Option<&mut Vec<Self>>;
572 fn truth(b: bool) -> Self;
574}
575
576pub trait Source<A>: Element {
578 fn read(self) -> A;
579 fn borrowed(_items: &[Self]) -> Option<&[A]> { None }
581}
582impl<A: Element> Source<A> for A {
583 #[inline]
584 fn read(self) -> A { self }
585 #[inline]
586 fn borrowed(items: &[A]) -> Option<&[A]> { Some(items) }
587}
588macro_rules! truth {
589 ($($a:ty),+) => {$(
590 impl Source<$a> for bool { #[inline] fn read(self) -> $a { self.into() } }
591 )+};
592}
593truth!(u8, i16, i32, i64);
594macro_rules! wider {
596 ($($s:ty => $($a:ty),+);+) => {$($(
597 impl Source<$a> for $s { #[inline] fn read(self) -> $a { self.into() } }
598 )+)+};
599}
600wider!(u8 => i16, i32, i64; i16 => i32, i64; i32 => i64);
601macro_rules! numbers {
603 ($($s:ty),+) => {$(
604 impl Source<f64> for $s { #[inline] fn read(self) -> f64 { crate::convert::float(self) } }
605 impl Source<f32> for $s { #[inline] fn read(self) -> f32 { crate::convert::float(self) } }
606 impl Source<half::f16> for $s { #[inline] fn read(self) -> half::f16 { crate::convert::float(self) } }
607 )+};
608}
609numbers!(u8, i16, i32, i64);
610macro_rules! truths {
612 ($($a:ty),+) => {$(
613 impl Source<$a> for bool { #[inline] fn read(self) -> $a { Source::<$a>::read(u8::from(self)) } }
614 )+};
615}
616truths!(f64, f32, half::f16);
617macro_rules! floats {
619 ($($s:ty => $a:ty: |$x:ident| $read:expr),+) => {$(
620 impl Source<$a> for $s { #[inline] fn read(self) -> $a { let $x = self; $read } }
621 )+};
622}
623floats!(
624 half::f16 => f64: |x| x.into(), f32 => f64: |x| x.into(), half::f16 => f32: |x| x.into(),
625 f64 => f32: |x| x as f32, f32 => half::f16: |x| half::f16::from_f32(x), f64 => half::f16: |x| half::f16::from_f64(x)
626);
627macro_rules! complex {
629 ($($s:ty),+) => {$(
630 impl Source<Complex64> for $s { #[inline] fn read(self) -> Complex64 { Complex64::new(Source::<f64>::read(self), 0.0) } }
631 impl Source<Complex32> for $s { #[inline] fn read(self) -> Complex32 { Complex32::new(Source::<f32>::read(self), 0.0) } }
632 )+};
633}
634complex!(bool, u8, i16, i32, i64, half::f16, f32, f64);
635impl Source<Complex64> for Complex32 {
636 #[inline]
637 fn read(self) -> Complex64 { Complex64::new(self.re.into(), self.im.into()) }
638}
639impl Source<Complex32> for Complex64 {
640 #[inline]
641 fn read(self) -> Complex32 { Complex32::new(self.re as f32, self.im as f32) }
642}
643
644pub fn read_all<A: Element, S: Source<A>>(items: &[S]) -> Vec<A> {
646 let mut out = Vec::with_capacity(items.len());
647 crate::pairs(crate::Arg::Many(items), crate::Arg::One(()), items.len(), &mut out, |x, ()| (x.read(), true));
648 out
649}
650
651fn overflow(x: impl std::fmt::Display) -> Error { Error::new(Kind::Overflow, format!("{x} doesn't fit the dtype it converts to")) }
653
654fn real_part(z: Complex64) -> Result<f64, Error> {
656 if z.im == 0.0 { Ok(z.re) } else { Err(Error::new(Kind::Domain, format!("{z} has an imaginary part, so it doesn't convert to a real dtype"))) }
657}
658
659fn integer(view: View<'_>, i: usize) -> Result<i64, Error> {
661 let x = match view {
662 View::Booleans(v) => return Ok(v[i].into()), View::Integers(v) => return Ok(v.get(i)), View::Floats(v) => v.get(i),
663 View::Complexes(v) => real_part(v.get(i))?, View::Characters(_) => unreachable!("cast refuses characters first")
664 };
665 let cast =
666 crate::convert::Conversion { input: DType::Float(FloatWidth::F64), output: DType::Integer(Width::I64), kind: crate::convert::ConversionKind::Cast };
667 if cast.validity::<f64, _>(&crate::recipe::NativeOps::<{ crate::FUSED }>::DEFAULT, x).is_some_and(|(_, valid)| valid) { Ok(x as i64) }
668 else { Err(overflow(x)) }
669}
670
671fn boolean(view: View<'_>, i: usize) -> Result<bool, Error> {
673 let x = match view {
674 View::Booleans(v) => return Ok(v[i]), View::Integers(v) => Source::<f64>::read(v.get(i)), View::Floats(v) => v.get(i),
675 View::Complexes(v) => real_part(v.get(i))?, View::Characters(_) => unreachable!("cast refuses characters first")
676 };
677 if truth(x) { Ok(x != 0.0) } else { Err(overflow(x)) }
678}
679#[inline]
681fn truth(x: f64) -> bool {
682 let cast = crate::convert::Conversion { input: DType::Float(FloatWidth::F64), output: DType::Boolean, kind: crate::convert::ConversionKind::Cast };
683 cast.validity::<f64, _>(&crate::recipe::NativeOps::<{ crate::FUSED }>::DEFAULT, x).is_some_and(|(_, valid)| valid)
684}
685fn truths<S: Copy + PartialEq + From<u8> + Source<f64>>(v: &[S], checked: bool, out: &mut Vec<bool>) -> Result<(), Error> {
687 let (zero, one) = (S::from(0), S::from(1));
688 if checked && !v.iter().fold(true, |ok, &x| ok & ((x == zero) | (x == one))) {
690 let x = v.iter().map(|&x| Source::<f64>::read(x)).find(|&x| !truth(x)).expect("an item that isn't a truth");
691 return Err(overflow(x));
692 }
693 out.extend(v.iter().map(|&x| x == one));
694 Ok(())
695}
696
697pub trait Cast: Element + crate::gather::Item {
699 fn cast(view: View<'_>, item: usize) -> Result<Self, Error>;
701 fn extend_cast(view: View<'_>, len: usize, checked: bool, out: &mut Vec<Self>) -> Result<(), Error> { itemwise(view, len, checked, out) }
703}
704pub(crate) fn kept<T: Element>(value: Result<T, Error>, checked: bool) -> Result<T, Error> {
706 match value { Ok(value) => Ok(value), Err(error) if checked => Err(error), Err(_) => Ok(T::FILL) }
707}
708fn itemwise<T: Cast>(view: View<'_>, len: usize, checked: bool, out: &mut Vec<T>) -> Result<(), Error> {
710 out.reserve(len);
711 for i in 0..len { out.push(kept(T::cast(view, i), checked)?); }
712 Ok(())
713}
714fn numeric(view: View<'_>) -> Result<(), Error> {
715 if matches!(view, View::Characters(_)) { Err(Error::new(Kind::Domain, "characters convert only to characters")) } else { Ok(()) }
716}
717fn real(view: View<'_>, item: usize) -> Result<f64, Error> {
718 Ok(match view {
719 View::Booleans(v) => u8::from(v[item]).into(), View::Integers(v) => Source::<f64>::read(v.get(item)), View::Floats(v) => v.get(item),
720 View::Complexes(v) => real_part(v.get(item))?, View::Characters(_) => return Err(Error::new(Kind::Domain, "characters convert only to characters"))
721 })
722}
723impl Cast for bool {
724 fn cast(view: View<'_>, item: usize) -> Result<Self, Error> { numeric(view)?; boolean(view, item) }
725 fn extend_cast(view: View<'_>, len: usize, checked: bool, out: &mut Vec<Self>) -> Result<(), Error> {
726 match view {
727 View::Booleans(v) => out.extend_from_slice(&v[..len]), View::Integers(v) => with_ints!(v, |v| truths(&v[..len], checked, out)?),
728 View::Floats(v) => with_floats!(v, |v| truths(&v[..len], checked, out)?), _ => return itemwise(view, len, checked, out)
729 }
730 Ok(())
731 }
732}
733impl Cast for char {
734 fn cast(view: View<'_>, item: usize) -> Result<Self, Error> {
735 match view { View::Characters(v) => Ok(v[item]), _ => Err(Error::new(Kind::Domain, "characters convert only to characters")) }
736 }
737}
738macro_rules! casts {
739 (integers $($t:ty),+) => {$(impl Cast for $t {
740 fn cast(view: View<'_>, item: usize) -> Result<Self, Error> {
741 numeric(view)?;
742 let value = integer(view, item)?;
743 Self::try_from(value).map_err(|_| overflow(value))
744 }
745 fn extend_cast(view: View<'_>, len: usize, checked: bool, out: &mut Vec<Self>) -> Result<(), Error> {
747 match view {
748 View::Booleans(v) => out.extend(v[..len].iter().map(|&b| Self::from(b))),
749 View::Integers(v) => with_ints!(v, |v| {
750 let v = &v[..len];
751 if checked { if let Some(&x) = v.iter().find(|&&x| Self::try_from(x).is_err()) { return Err(overflow(x)); } }
752 out.extend(v.iter().map(|&x| Self::try_from(x).unwrap_or(Self::FILL)));
753 }),
754 _ => return itemwise(view, len, checked, out),
755 }
756 Ok(())
757 }
758 })+};
759 (floats $($t:ty),+) => {$(impl Cast for $t {
760 fn cast(view: View<'_>, item: usize) -> Result<Self, Error> { real(view, item).map(Source::<Self>::read) }
761 fn extend_cast(view: View<'_>, len: usize, checked: bool, out: &mut Vec<Self>) -> Result<(), Error> {
763 match view {
764 View::Booleans(v) => out.extend(v[..len].iter().map(|&b| Source::<Self>::read(f64::from(u8::from(b))))),
765 View::Integers(v) => with_ints!(v, |v| out.extend(v[..len].iter().map(|&x| Source::<Self>::read(Source::<f64>::read(x))))),
766 View::Floats(v) => with_floats!(v, |v| out.extend(v[..len].iter().map(|&x| Source::<Self>::read(f64::from(x))))),
767 _ => return itemwise(view, len, checked, out),
768 }
769 Ok(())
770 }
771 })+};
772 (complex $($t:ty),+) => {$(impl Cast for $t {
773 fn cast(view: View<'_>, item: usize) -> Result<Self, Error> {
774 let value = match view { View::Complexes(v) => v.get(item), _ => Complex64::new(real(view, item)?, 0.0) };
775 Ok(Source::<Self>::read(value))
776 }
777 })+};
778}
779casts!(integers u8, i16, i32, i64);
780casts!(floats half::f16, f32, f64);
781casts!(complex Complex32, Complex64);
782
783impl Buffer {
784 pub fn nonzero(view: View<'_>) -> Vec<usize> {
786 with_dtype!(view.dtype(), T => T::of(view).expect("matching dtype").iter().enumerate().filter_map(|(i, &x)| (x != T::FILL).then_some(i)).collect())
787 }
788 pub fn any_fill(view: View<'_>) -> bool {
790 with_dtype!(view.dtype(), T => T::of(view).expect("matching dtype").iter().fold(false, |found, &x| found | (x == T::FILL)))
791 }
792 pub fn same(view: View<'_>) -> bool {
794 let size = view.dtype().bytes();
795 let bytes = unsafe { std::slice::from_raw_parts(view.as_ptr(), view.len() * size) };
797 bytes.len() <= size || bytes[size..] == bytes[..bytes.len() - size]
799 }
800 pub fn walked(view: View<'_>, base: usize, steps: &[crate::gather::Steps], n: usize) -> Self {
802 with_dtype!(view.dtype(), T => {
803 let mut out = Vec::with_capacity(n);
804 let (base, plan) = crate::gather::Steps::simplify(base, steps);
805 crate::gather::walk_plan(&mut out, T::of(view).expect("matching dtype"), base, &plan, T::FILL, 0, n, crate::gather::Same);
806 T::buffer(out)
807 })
808 }
809 pub fn ordered(self, order: Option<Vec<crate::gather::Steps>>) -> Self {
811 match order { Some(order) => Self::walked(self.view(), 0, &order, crate::gather::Steps::count(&order)), None => self }
812 }
813 pub fn copied(view: View<'_>, range: std::ops::Range<usize>) -> Self {
815 let mut b = Self::with_capacity(view.dtype(), range.len());
816 b.extend_from(view, range);
817 b
818 }
819 pub fn gathered<I: crate::gather::IndexValue>(view: View<'_>, indices: &[I]) -> Self {
821 fn taken<T: Element, I: crate::gather::IndexValue>(items: &[T], indices: &[I]) -> Buffer {
822 let mut out = Vec::with_capacity(indices.len());
823 crate::gather::take(&mut out, items, indices, |x| x);
824 T::buffer(out)
825 }
826 match view {
827 View::Booleans(v) => taken(v, indices), View::Characters(v) => taken(v, indices), View::Integers(v) => with_ints!(v, |v| taken(v, indices)),
828 View::Floats(v) => with_floats!(v, |v| taken(v, indices)), View::Complexes(v) => with_complexes!(v, |v| taken(v, indices))
829 }
830 }
831 pub fn cast(view: View<'_>, dtype: DType) -> Result<Self, Error> { Self::cast_mapped(view, &crate::agreement::Mapping::Linear(1), view.len(), dtype) }
833 pub fn kept(view: View<'_>, dtype: DType) -> Result<Self, Error> {
835 let whole = match view {
836 View::Floats(v) => (0..v.len()).all(|i| v.get(i).fract() == 0.0), View::Complexes(v) => (0..v.len()).all(|i| v.get(i).re.fract() == 0.0), _ => true
837 };
838 let lost = || Error::new(Kind::Domain, format!("a {} item doesn't keep its value as {}", view.dtype().name(), dtype.name()));
839 if dtype.is_integral() && !whole { return Err(lost()); }
840 Self::cast(view, dtype).map_err(|_| lost())
841 }
842 pub fn cast_mapped(view: View<'_>, mapping: &crate::agreement::Mapping, n: usize, dtype: DType) -> Result<Self, Error> {
844 use crate::agreement::{Binding, Missing, Read, ReadPlan};
845 let mut sources = vec![Binding::full(view)];
846 let missing = Missing::prototype(view.dtype(), &mut sources);
847 let plan = ReadPlan::copy(0, view.len(), mapping.clone(), n, missing);
848 let mut output = Self::with_capacity(dtype, n);
849 Read { sources: &sources, plan: &plan }.read_into(0..n, dtype, true, &mut output)?;
850 Ok(output)
851 }
852}
853
854impl Buffer {
855 pub fn floored(view: View<'_>, dtype: DType, t: impl crate::tolerant::Tolerant) -> Result<Self, Error> {
857 match (view, dtype) {
858 (View::Floats(values), DType::Integer(width)) => {
859 Ok(with_width!(width, I => I::buffer(with_floats!(values, |values| values.iter().map(|&x| crate::convert::floored::<I, _>(x, t)).collect()))))
860 }
861 (View::Integers(_) | View::Booleans(_), DType::Integer(_)) => Self::cast_results(view, dtype, false),
862 _ => Self::cast(view, dtype),
863 }
864 }
865 pub fn cast_results(view: View<'_>, dtype: DType, checked: bool) -> Result<Self, Error> {
866 match (view, dtype) {
867 (View::Floats(values), DType::Integer(width)) => {
868 Ok(with_width!(width, I => I::buffer(with_floats!(values, |values| values.iter().map(|&x| crate::convert::saturated::<I, _>(x)).collect()))))
869 }
870 (View::Integers(values), DType::Integer(width)) if !checked => {
871 Ok(with_width!(width, T => with_ints!(values, |values| T::buffer(values.iter().map(|&x| x as T).collect()))))
872 }
873 (View::Booleans(values), DType::Integer(width)) => Ok(with_width!(width, T => T::buffer(values.iter().map(|&x| x as T).collect()))),
874 (_, DType::Character) if view.dtype().is_integral() => {
875 let items = (0..view.len()).map(|i| {
876 let value = integer(view, i).ok().and_then(|x| u32::try_from(x).ok()).and_then(char::from_u32);
877 match value {
878 Some(value) => Ok(value), None if checked => Err(Error::new(Kind::Domain, "result is not a Unicode character")), None => Ok(char::FILL)
879 }
880 }).collect::<Result<Vec<_>, _>>()?;
881 Ok(Self::Characters(items))
882 }
883 _ => with_dtype!(dtype, T => {
884 let mut items = Vec::new();
885 T::extend_cast(view, view.len(), checked, &mut items)?;
886 Ok(T::buffer(items))
887 }),
888 }
889 }
890}