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