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