1use std::cmp::Ordering;
7use std::fmt::{Debug, Display, Formatter};
8use std::hash::Hash;
9use std::ops::AddAssign;
10use std::panic::RefUnwindSafe;
11
12use num_traits::bounds::UpperBounded;
13use num_traits::{
14 AsPrimitive, Bounded, FromPrimitive, Num, NumCast, PrimInt, ToPrimitive, Unsigned,
15};
16use vortex_error::{VortexError, VortexResult, vortex_err};
17
18use crate::DType;
19use crate::half::f16;
20use crate::nullability::Nullability::NonNullable;
21
22#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Hash, prost::Enumeration)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
26#[repr(u8)]
27pub enum PType {
28 U8 = 0,
30 U16 = 1,
32 U32 = 2,
34 U64 = 3,
36 I8 = 4,
38 I16 = 5,
40 I32 = 6,
42 I64 = 7,
44 F16 = 8,
46 F32 = 9,
48 F64 = 10,
50}
51
52pub trait IntegerPType:
59 NativePType + PrimInt + ToPrimitive + Bounded + AddAssign + AsPrimitive<usize>
60{
61 fn max_value_as_u64() -> u64 {
63 Self::PTYPE.max_value_as_u64()
64 }
65}
66
67impl<T> IntegerPType for T where
69 T: NativePType + PrimInt + ToPrimitive + Bounded + AddAssign + AsPrimitive<usize>
70{
71}
72
73pub trait UnsignedPType: IntegerPType + Unsigned {}
80
81impl<T> UnsignedPType for T where T: IntegerPType + Unsigned {}
83
84pub trait NativePType:
89 Send
90 + Sync
91 + Clone
92 + Copy
93 + Debug
94 + Display
95 + Default
96 + RefUnwindSafe
97 + Num
98 + NumCast
99 + FromPrimitive
100 + ToBytes
101 + TryFromBytes
102 + 'static
103{
104 const PTYPE: PType;
106
107 fn is_nan(self) -> bool;
110
111 fn is_infinite(self) -> bool;
114
115 fn total_compare(self, other: Self) -> Ordering;
117
118 #[inline]
120 fn is_le(self, other: Self) -> bool {
121 self.total_compare(other).is_le()
122 }
123
124 #[inline]
126 fn is_lt(self, other: Self) -> bool {
127 self.total_compare(other).is_lt()
128 }
129
130 #[inline]
132 fn is_ge(self, other: Self) -> bool {
133 self.total_compare(other).is_ge()
134 }
135
136 #[inline]
138 fn is_gt(self, other: Self) -> bool {
139 self.total_compare(other).is_gt()
140 }
141
142 fn is_eq(self, other: Self) -> bool;
144
145 fn downcast<V: PTypeVisitor + ?Sized>(visitor: &V) -> V::Output<Self>;
147
148 fn downcast_mut<V: PTypeVisitorMut + ?Sized>(visitor: &mut V) -> V::Output<Self>;
150}
151
152#[allow(missing_docs)] pub trait PTypeVisitor {
155 type Output<T: NativePType>;
156
157 fn as_u8(&self) -> Self::Output<u8>;
158 fn as_u16(&self) -> Self::Output<u16>;
159 fn as_u32(&self) -> Self::Output<u32>;
160 fn as_u64(&self) -> Self::Output<u64>;
161 fn as_i8(&self) -> Self::Output<i8>;
162 fn as_i16(&self) -> Self::Output<i16>;
163 fn as_i32(&self) -> Self::Output<i32>;
164 fn as_i64(&self) -> Self::Output<i64>;
165 fn as_f16(&self) -> Self::Output<f16>;
166 fn as_f32(&self) -> Self::Output<f32>;
167 fn as_f64(&self) -> Self::Output<f64>;
168}
169
170pub trait PTypeVisitorExt: PTypeVisitor {
172 fn as_primitive<T: NativePType>(&self) -> Self::Output<T> {
174 T::downcast(self)
175 }
176}
177
178impl<T: PTypeVisitor + ?Sized> PTypeVisitorExt for T {}
179
180#[allow(missing_docs)] pub trait PTypeVisitorMut {
183 type Output<T: NativePType>;
184
185 fn as_u8(&mut self) -> Self::Output<u8>;
186 fn as_u16(&mut self) -> Self::Output<u16>;
187 fn as_u32(&mut self) -> Self::Output<u32>;
188 fn as_u64(&mut self) -> Self::Output<u64>;
189 fn as_i8(&mut self) -> Self::Output<i8>;
190 fn as_i16(&mut self) -> Self::Output<i16>;
191 fn as_i32(&mut self) -> Self::Output<i32>;
192 fn as_i64(&mut self) -> Self::Output<i64>;
193 fn as_f16(&mut self) -> Self::Output<f16>;
194 fn as_f32(&mut self) -> Self::Output<f32>;
195 fn as_f64(&mut self) -> Self::Output<f64>;
196}
197
198pub trait PTypeVisitorMutExt: PTypeVisitorMut {
200 fn as_primitive_mut<T: NativePType>(&mut self) -> Self::Output<T> {
202 T::downcast_mut(self)
203 }
204}
205
206macro_rules! impl_ptype_downcast {
207 ($T:ty) => {
208 #[inline]
209 fn downcast<V: PTypeVisitor + ?Sized>(visitor: &V) -> V::Output<Self> {
210 paste::paste! { visitor.[<as_ $T>]() }
211 }
212
213 #[inline]
214 fn downcast_mut<V: PTypeVisitorMut + ?Sized>(visitor: &mut V) -> V::Output<Self> {
215 paste::paste! { visitor.[<as_ $T>]() }
216 }
217 };
218}
219
220macro_rules! native_ptype {
221 ($T:ty, $ptype:tt) => {
222 impl crate::NativeDType for $T {
223 fn dtype() -> DType {
224 DType::Primitive(PType::$ptype, crate::Nullability::NonNullable)
225 }
226 }
227
228 impl NativePType for $T {
229 const PTYPE: PType = PType::$ptype;
230
231 #[inline]
232 fn is_nan(self) -> bool {
233 false
234 }
235
236 #[inline]
237 fn is_infinite(self) -> bool {
238 false
239 }
240
241 #[inline]
242 fn total_compare(self, other: Self) -> Ordering {
243 self.cmp(&other)
244 }
245
246 #[inline]
247 fn is_eq(self, other: Self) -> bool {
248 self == other
249 }
250
251 impl_ptype_downcast!($T);
252 }
253 };
254}
255
256impl<T: PTypeVisitorMut + ?Sized> PTypeVisitorMutExt for T {}
257
258macro_rules! native_float_ptype {
259 ($T:ty, $ptype:tt) => {
260 impl crate::NativeDType for $T {
261 fn dtype() -> DType {
262 DType::Primitive(PType::$ptype, crate::Nullability::NonNullable)
263 }
264 }
265
266 impl NativePType for $T {
267 const PTYPE: PType = PType::$ptype;
268
269 #[inline]
270 fn is_nan(self) -> bool {
271 <$T>::is_nan(self)
272 }
273
274 #[inline]
275 fn is_infinite(self) -> bool {
276 <$T>::is_infinite(self)
277 }
278
279 #[inline]
280 fn total_compare(self, other: Self) -> Ordering {
281 self.total_cmp(&other)
282 }
283
284 #[inline]
285 fn is_eq(self, other: Self) -> bool {
286 self.to_bits() == other.to_bits()
287 }
288
289 impl_ptype_downcast!($T);
290 }
291 };
292}
293
294native_ptype!(u8, U8);
295native_ptype!(u16, U16);
296native_ptype!(u32, U32);
297native_ptype!(u64, U64);
298native_ptype!(i8, I8);
299native_ptype!(i16, I16);
300native_ptype!(i32, I32);
301native_ptype!(i64, I64);
302native_float_ptype!(f16, F16);
303native_float_ptype!(f32, F32);
304native_float_ptype!(f64, F64);
305
306#[macro_export]
308macro_rules! match_each_native_ptype {
309 (
310 $self:expr,integral: |
311 $integral_enc:ident |
312 $intbody:block,floating: |
313 $floating_point_enc:ident |
314 $floatbody:block
315 ) => {{
316 use $crate::PType;
317 use $crate::half::f16;
318 match $self {
319 PType::I8 => {
320 type $integral_enc = i8;
321 $intbody
322 }
323 PType::I16 => {
324 type $integral_enc = i16;
325 $intbody
326 }
327 PType::I32 => {
328 type $integral_enc = i32;
329 $intbody
330 }
331 PType::I64 => {
332 type $integral_enc = i64;
333 $intbody
334 }
335 PType::U8 => {
336 type $integral_enc = u8;
337 $intbody
338 }
339 PType::U16 => {
340 type $integral_enc = u16;
341 $intbody
342 }
343 PType::U32 => {
344 type $integral_enc = u32;
345 $intbody
346 }
347 PType::U64 => {
348 type $integral_enc = u64;
349 $intbody
350 }
351 PType::F16 => {
352 type $floating_point_enc = f16;
353 $floatbody
354 }
355 PType::F32 => {
356 type $floating_point_enc = f32;
357 $floatbody
358 }
359 PType::F64 => {
360 type $floating_point_enc = f64;
361 $floatbody
362 }
363 }
364 }};
365 (
366 $self:expr,unsigned: |
367 $unsigned_enc:ident |
368 $unsigned_body:block,signed: |
369 $signed_enc:ident |
370 $signed_body:block,floating: |
371 $floating_point_enc:ident |
372 $floating_point_body:block
373 ) => {{
374 use $crate::PType;
375 use $crate::half::f16;
376 match $self {
377 PType::U8 => {
378 type $unsigned_enc = u8;
379 $unsigned_body
380 }
381 PType::U16 => {
382 type $unsigned_enc = u16;
383 $unsigned_body
384 }
385 PType::U32 => {
386 type $unsigned_enc = u32;
387 $unsigned_body
388 }
389 PType::U64 => {
390 type $unsigned_enc = u64;
391 $unsigned_body
392 }
393 PType::I8 => {
394 type $signed_enc = i8;
395 $signed_body
396 }
397 PType::I16 => {
398 type $signed_enc = i16;
399 $signed_body
400 }
401 PType::I32 => {
402 type $signed_enc = i32;
403 $signed_body
404 }
405 PType::I64 => {
406 type $signed_enc = i64;
407 $signed_body
408 }
409 PType::F16 => {
410 type $floating_point_enc = f16;
411 $floating_point_body
412 }
413 PType::F32 => {
414 type $floating_point_enc = f32;
415 $floating_point_body
416 }
417 PType::F64 => {
418 type $floating_point_enc = f64;
419 $floating_point_body
420 }
421 }
422 }};
423 ($self:expr, | $tname:ident | $body:block) => {{
424 use $crate::PType;
425 use $crate::half::f16;
426 match $self {
427 PType::I8 => {
428 type $tname = i8;
429 $body
430 }
431 PType::I16 => {
432 type $tname = i16;
433 $body
434 }
435 PType::I32 => {
436 type $tname = i32;
437 $body
438 }
439 PType::I64 => {
440 type $tname = i64;
441 $body
442 }
443 PType::U8 => {
444 type $tname = u8;
445 $body
446 }
447 PType::U16 => {
448 type $tname = u16;
449 $body
450 }
451 PType::U32 => {
452 type $tname = u32;
453 $body
454 }
455 PType::U64 => {
456 type $tname = u64;
457 $body
458 }
459 PType::F16 => {
460 type $tname = f16;
461 $body
462 }
463 PType::F32 => {
464 type $tname = f32;
465 $body
466 }
467 PType::F64 => {
468 type $tname = f64;
469 $body
470 }
471 }
472 }};
473}
474
475#[macro_export]
477macro_rules! match_each_integer_ptype {
478 ($self:expr, | $enc:ident | $body:block) => {{
479 use $crate::PType;
480 match $self {
481 PType::I8 => {
482 type $enc = i8;
483 $body
484 }
485 PType::I16 => {
486 type $enc = i16;
487 $body
488 }
489 PType::I32 => {
490 type $enc = i32;
491 $body
492 }
493 PType::I64 => {
494 type $enc = i64;
495 $body
496 }
497 PType::U8 => {
498 type $enc = u8;
499 $body
500 }
501 PType::U16 => {
502 type $enc = u16;
503 $body
504 }
505 PType::U32 => {
506 type $enc = u32;
507 $body
508 }
509 PType::U64 => {
510 type $enc = u64;
511 $body
512 }
513 other => panic!("Unsupported ptype {other}"),
514 }
515 }};
516}
517
518#[macro_export]
520macro_rules! match_each_unsigned_integer_ptype {
521 ($self:expr, | $enc:ident | $body:block) => {{
522 use $crate::PType;
523 match $self {
524 PType::U8 => {
525 type $enc = u8;
526 $body
527 }
528 PType::U16 => {
529 type $enc = u16;
530 $body
531 }
532 PType::U32 => {
533 type $enc = u32;
534 $body
535 }
536 PType::U64 => {
537 type $enc = u64;
538 $body
539 }
540 other => panic!("Unsupported ptype {other}"),
541 }
542 }};
543}
544
545#[macro_export]
547macro_rules! match_each_signed_integer_ptype {
548 ($self:expr, | $enc:ident | $body:block) => {{
549 use $crate::PType;
550 match $self {
551 PType::I8 => {
552 type $enc = i8;
553 $body
554 }
555 PType::I16 => {
556 type $enc = i16;
557 $body
558 }
559 PType::I32 => {
560 type $enc = i32;
561 $body
562 }
563 PType::I64 => {
564 type $enc = i64;
565 $body
566 }
567 other => panic!("Unsupported ptype {other}"),
568 }
569 }};
570}
571
572#[macro_export]
574macro_rules! match_each_float_ptype {
575 ($self:expr, | $enc:ident | $body:block) => {{
576 use vortex_dtype::half::f16;
577 use $crate::PType;
578 match $self {
579 PType::F16 => {
580 type $enc = f16;
581 $body
582 }
583 PType::F32 => {
584 type $enc = f32;
585 $body
586 }
587 PType::F64 => {
588 type $enc = f64;
589 $body
590 }
591 other => panic!("Unsupported ptype {other}"),
592 }
593 }};
594}
595
596#[macro_export]
600macro_rules! match_each_native_simd_ptype {
601 ($self:expr, | $enc:ident | $body:block) => {{
602 use $crate::PType;
603 match $self {
604 PType::I8 => {
605 type $enc = i8;
606 $body
607 }
608 PType::I16 => {
609 type $enc = i16;
610 $body
611 }
612 PType::I32 => {
613 type $enc = i32;
614 $body
615 }
616 PType::I64 => {
617 type $enc = i64;
618 $body
619 }
620 PType::U8 => {
621 type $enc = u8;
622 $body
623 }
624 PType::U16 => {
625 type $enc = u16;
626 $body
627 }
628 PType::U32 => {
629 type $enc = u32;
630 $body
631 }
632 PType::U64 => {
633 type $enc = u64;
634 $body
635 }
636 PType::F16 => panic!("f16 does not implement simd::SimdElement"),
637 PType::F32 => {
638 type $enc = f32;
639 $body
640 }
641 PType::F64 => {
642 type $enc = f64;
643 $body
644 }
645 }
646 }};
647}
648
649impl PType {
650 #[inline]
652 pub const fn is_unsigned_int(self) -> bool {
653 matches!(self, Self::U8 | Self::U16 | Self::U32 | Self::U64)
654 }
655
656 #[inline]
658 pub const fn is_signed_int(self) -> bool {
659 matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64)
660 }
661
662 #[inline]
665 pub const fn is_int(self) -> bool {
666 self.is_unsigned_int() || self.is_signed_int()
667 }
668
669 #[inline]
671 pub const fn is_float(self) -> bool {
672 matches!(self, Self::F16 | Self::F32 | Self::F64)
673 }
674
675 #[inline]
677 pub const fn byte_width(&self) -> usize {
678 match_each_native_ptype!(self, |T| { size_of::<T>() })
679 }
680
681 #[inline]
683 pub const fn bit_width(&self) -> usize {
684 self.byte_width() * 8
685 }
686
687 #[inline]
690 pub fn max_value_as_u64(&self) -> u64 {
691 match_each_native_ptype!(self, |T| {
692 <T as UpperBounded>::max_value()
693 .to_u64()
694 .unwrap_or(u64::MAX)
695 })
696 }
697
698 #[inline]
700 pub const fn to_signed(self) -> Self {
701 match self {
702 Self::U8 => Self::I8,
703 Self::U16 => Self::I16,
704 Self::U32 => Self::I32,
705 Self::U64 => Self::I64,
706 Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::F16 | Self::F32 | Self::F64 => {
707 self
708 }
709 }
710 }
711
712 #[inline]
715 pub const fn to_unsigned(self) -> Self {
716 match self {
717 Self::I8 => Self::U8,
718 Self::I16 => Self::U16,
719 Self::I32 => Self::U32,
720 Self::I64 => Self::U64,
721 Self::U8 | Self::U16 | Self::U32 | Self::U64 | Self::F16 | Self::F32 | Self::F64 => {
722 self
723 }
724 }
725 }
726}
727
728impl Display for PType {
729 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
730 match self {
731 Self::U8 => write!(f, "u8"),
732 Self::U16 => write!(f, "u16"),
733 Self::U32 => write!(f, "u32"),
734 Self::U64 => write!(f, "u64"),
735 Self::I8 => write!(f, "i8"),
736 Self::I16 => write!(f, "i16"),
737 Self::I32 => write!(f, "i32"),
738 Self::I64 => write!(f, "i64"),
739 Self::F16 => write!(f, "f16"),
740 Self::F32 => write!(f, "f32"),
741 Self::F64 => write!(f, "f64"),
742 }
743 }
744}
745
746impl TryFrom<&DType> for PType {
747 type Error = VortexError;
748
749 #[inline]
750 fn try_from(value: &DType) -> VortexResult<Self> {
751 if let DType::Primitive(p, _) = value {
752 Ok(*p)
753 } else {
754 Err(vortex_err!("Cannot convert DType {} into PType", value))
755 }
756 }
757}
758
759impl From<PType> for &DType {
760 fn from(item: PType) -> Self {
761 match item {
763 PType::I8 => &DType::Primitive(PType::I8, NonNullable),
764 PType::I16 => &DType::Primitive(PType::I16, NonNullable),
765 PType::I32 => &DType::Primitive(PType::I32, NonNullable),
766 PType::I64 => &DType::Primitive(PType::I64, NonNullable),
767 PType::U8 => &DType::Primitive(PType::U8, NonNullable),
768 PType::U16 => &DType::Primitive(PType::U16, NonNullable),
769 PType::U32 => &DType::Primitive(PType::U32, NonNullable),
770 PType::U64 => &DType::Primitive(PType::U64, NonNullable),
771 PType::F16 => &DType::Primitive(PType::F16, NonNullable),
772 PType::F32 => &DType::Primitive(PType::F32, NonNullable),
773 PType::F64 => &DType::Primitive(PType::F64, NonNullable),
774 }
775 }
776}
777
778impl From<PType> for DType {
779 fn from(item: PType) -> Self {
780 DType::Primitive(item, NonNullable)
781 }
782}
783
784pub trait ToBytes: Sized {
786 fn to_le_bytes(&self) -> &[u8];
788}
789
790pub trait TryFromBytes: Sized {
792 fn try_from_le_bytes(bytes: &[u8]) -> VortexResult<Self>;
794}
795
796macro_rules! try_from_bytes {
797 ($T:ty) => {
798 impl ToBytes for $T {
799 #[inline]
800 #[allow(clippy::size_of_in_element_count)]
801 fn to_le_bytes(&self) -> &[u8] {
802 let raw_ptr = self as *const $T as *const u8;
805 unsafe { std::slice::from_raw_parts(raw_ptr, std::mem::size_of::<$T>()) }
806 }
807 }
808
809 impl TryFromBytes for $T {
810 fn try_from_le_bytes(bytes: &[u8]) -> VortexResult<Self> {
811 Ok(<$T>::from_le_bytes(bytes.try_into().map_err(|_| {
812 vortex_err!("Failed to convert bytes into {}", stringify!($T))
813 })?))
814 }
815 }
816 };
817}
818
819try_from_bytes!(u8);
820try_from_bytes!(u16);
821try_from_bytes!(u32);
822try_from_bytes!(u64);
823try_from_bytes!(i8);
824try_from_bytes!(i16);
825try_from_bytes!(i32);
826try_from_bytes!(i64);
827try_from_bytes!(f16);
828try_from_bytes!(f32);
829try_from_bytes!(f64);
830
831pub trait PhysicalPType: NativePType {
833 type Physical: NativePType + Unsigned;
835}
836
837macro_rules! physical_ptype {
838 ($T:ty, $U:ty) => {
839 impl PhysicalPType for $T {
840 type Physical = $U;
841 }
842 };
843}
844
845physical_ptype!(i8, u8);
846physical_ptype!(i16, u16);
847physical_ptype!(i32, u32);
848physical_ptype!(i64, u64);
849physical_ptype!(u8, u8);
850physical_ptype!(u16, u16);
851physical_ptype!(u32, u32);
852physical_ptype!(u64, u64);
853
854#[cfg(test)]
855mod tests {
856 use super::*;
857
858 #[test]
859 fn try_from_bytes() {
860 assert_eq!(u8::try_from_le_bytes(&[0x01]).unwrap(), 0x01);
861 assert_eq!(u16::try_from_le_bytes(&[0x01, 0x02]).unwrap(), 0x0201);
862 assert_eq!(
863 u32::try_from_le_bytes(&[0x01, 0x02, 0x03, 0x04]).unwrap(),
864 0x04030201
865 );
866 assert_eq!(
867 u64::try_from_le_bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]).unwrap(),
868 0x0807060504030201
869 );
870 }
871
872 #[test]
873 fn to_bytes_rt() {
874 assert_eq!(&0x01u8.to_le_bytes(), &[0x01]);
875 assert_eq!(&0x0201u16.to_le_bytes(), &[0x01, 0x02]);
876
877 assert_eq!(u8::try_from_le_bytes(&42_u8.to_le_bytes()).unwrap(), 42);
878 assert_eq!(u16::try_from_le_bytes(&42_u16.to_le_bytes()).unwrap(), 42);
879 assert_eq!(u32::try_from_le_bytes(&42_u32.to_le_bytes()).unwrap(), 42);
880 assert_eq!(u64::try_from_le_bytes(&42_u64.to_le_bytes()).unwrap(), 42);
881 assert_eq!(i8::try_from_le_bytes(&42_i8.to_le_bytes()).unwrap(), 42);
882 assert_eq!(i16::try_from_le_bytes(&42_i16.to_le_bytes()).unwrap(), 42);
883 assert_eq!(i32::try_from_le_bytes(&42_i32.to_le_bytes()).unwrap(), 42);
884 assert_eq!(i64::try_from_le_bytes(&42_i64.to_le_bytes()).unwrap(), 42);
885 assert_eq!(
886 f16::try_from_le_bytes(&f16::from_f32(42.0).to_le_bytes()).unwrap(),
887 f16::from_f32(42.0)
888 );
889 assert_eq!(
890 f32::try_from_le_bytes(&42.0_f32.to_le_bytes()).unwrap(),
891 42.0
892 );
893 assert_eq!(
894 f64::try_from_le_bytes(&42.0_f64.to_le_bytes()).unwrap(),
895 42.0
896 );
897 }
898
899 #[test]
900 fn max_value_u64() {
901 assert_eq!(PType::U8.max_value_as_u64(), u8::MAX as u64);
902 assert_eq!(PType::U16.max_value_as_u64(), u16::MAX as u64);
903 assert_eq!(PType::U32.max_value_as_u64(), u32::MAX as u64);
904 assert_eq!(PType::U64.max_value_as_u64(), u64::MAX);
905 assert_eq!(PType::I8.max_value_as_u64(), i8::MAX as u64);
906 assert_eq!(PType::I16.max_value_as_u64(), i16::MAX as u64);
907 assert_eq!(PType::I32.max_value_as_u64(), i32::MAX as u64);
908 assert_eq!(PType::I64.max_value_as_u64(), i64::MAX as u64);
909 assert_eq!(PType::F16.max_value_as_u64(), 65504); assert_eq!(PType::F32.max_value_as_u64(), u64::MAX);
911 assert_eq!(PType::F64.max_value_as_u64(), u64::MAX);
912 }
913
914 #[test]
915 fn widths() {
916 assert_eq!(PType::U8.byte_width(), 1);
917 assert_eq!(PType::U16.byte_width(), 2);
918 assert_eq!(PType::U32.byte_width(), 4);
919 assert_eq!(PType::U64.byte_width(), 8);
920 assert_eq!(PType::I8.byte_width(), 1);
921 assert_eq!(PType::I16.byte_width(), 2);
922 assert_eq!(PType::I32.byte_width(), 4);
923 assert_eq!(PType::I64.byte_width(), 8);
924 assert_eq!(PType::F16.byte_width(), 2);
925 assert_eq!(PType::F32.byte_width(), 4);
926 assert_eq!(PType::F64.byte_width(), 8);
927
928 assert_eq!(PType::U8.bit_width(), 8);
929 assert_eq!(PType::U16.bit_width(), 16);
930 assert_eq!(PType::U32.bit_width(), 32);
931 assert_eq!(PType::U64.bit_width(), 64);
932 assert_eq!(PType::I8.bit_width(), 8);
933 assert_eq!(PType::I16.bit_width(), 16);
934 assert_eq!(PType::I32.bit_width(), 32);
935 assert_eq!(PType::I64.bit_width(), 64);
936 assert_eq!(PType::F16.bit_width(), 16);
937 assert_eq!(PType::F32.bit_width(), 32);
938 assert_eq!(PType::F64.bit_width(), 64);
939 }
940
941 #[test]
942 fn native_ptype_nan_handling() {
943 let a = f32::NAN;
944 let b = f32::NAN;
945 assert_ne!(a, b);
946 assert!(<f32 as NativePType>::is_nan(a));
947 assert!(<f32 as NativePType>::is_nan(b));
948 assert!(<f32 as NativePType>::is_eq(a, b));
949 assert!(<f32 as NativePType>::total_compare(a, b) == Ordering::Equal);
950 }
951
952 #[test]
953 fn to_signed() {
954 assert_eq!(PType::U8.to_signed(), PType::I8);
955 assert_eq!(PType::U16.to_signed(), PType::I16);
956 assert_eq!(PType::U32.to_signed(), PType::I32);
957 assert_eq!(PType::U64.to_signed(), PType::I64);
958 assert_eq!(PType::I8.to_signed(), PType::I8);
959 assert_eq!(PType::I16.to_signed(), PType::I16);
960 assert_eq!(PType::I32.to_signed(), PType::I32);
961 assert_eq!(PType::I64.to_signed(), PType::I64);
962 assert_eq!(PType::F16.to_signed(), PType::F16);
963 assert_eq!(PType::F32.to_signed(), PType::F32);
964 assert_eq!(PType::F64.to_signed(), PType::F64);
965 }
966
967 #[test]
968 fn to_unsigned() {
969 assert_eq!(PType::U8.to_unsigned(), PType::U8);
970 assert_eq!(PType::U16.to_unsigned(), PType::U16);
971 assert_eq!(PType::U32.to_unsigned(), PType::U32);
972 assert_eq!(PType::U64.to_unsigned(), PType::U64);
973 assert_eq!(PType::I8.to_unsigned(), PType::U8);
974 assert_eq!(PType::I16.to_unsigned(), PType::U16);
975 assert_eq!(PType::I32.to_unsigned(), PType::U32);
976 assert_eq!(PType::I64.to_unsigned(), PType::U64);
977 assert_eq!(PType::F16.to_unsigned(), PType::F16);
978 assert_eq!(PType::F32.to_unsigned(), PType::F32);
979 assert_eq!(PType::F64.to_unsigned(), PType::F64);
980 }
981
982 #[test]
983 fn to_dtype() {
984 assert_eq!(
985 DType::from(PType::U8),
986 DType::Primitive(PType::U8, NonNullable)
987 );
988 assert_eq!(
989 DType::from(PType::U16),
990 DType::Primitive(PType::U16, NonNullable)
991 );
992 assert_eq!(
993 DType::from(PType::U32),
994 DType::Primitive(PType::U32, NonNullable)
995 );
996 assert_eq!(
997 DType::from(PType::U64),
998 DType::Primitive(PType::U64, NonNullable)
999 );
1000 assert_eq!(
1001 DType::from(PType::I8),
1002 DType::Primitive(PType::I8, NonNullable)
1003 );
1004 assert_eq!(
1005 DType::from(PType::I16),
1006 DType::Primitive(PType::I16, NonNullable)
1007 );
1008 assert_eq!(
1009 DType::from(PType::I32),
1010 DType::Primitive(PType::I32, NonNullable)
1011 );
1012 assert_eq!(
1013 DType::from(PType::I64),
1014 DType::Primitive(PType::I64, NonNullable)
1015 );
1016 assert_eq!(
1017 DType::from(PType::F16),
1018 DType::Primitive(PType::F16, NonNullable)
1019 );
1020 assert_eq!(
1021 DType::from(PType::F32),
1022 DType::Primitive(PType::F32, NonNullable)
1023 );
1024 assert_eq!(
1025 DType::from(PType::F64),
1026 DType::Primitive(PType::F64, NonNullable)
1027 );
1028 }
1029}