1use bytemuck::{Pod, Zeroable};
2use half::f16;
3use std::fmt;
4
5use crate::error::{Result, TrxError};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum DType {
10 Float16,
11 Float32,
12 Float64,
13 Int8,
14 Int16,
15 Int32,
16 Int64,
17 UInt8,
18 UInt16,
19 UInt32,
20 UInt64,
21}
22
23impl DType {
24 pub fn size_of(self) -> usize {
26 match self {
27 DType::Int8 | DType::UInt8 => 1,
28 DType::Float16 | DType::Int16 | DType::UInt16 => 2,
29 DType::Float32 | DType::Int32 | DType::UInt32 => 4,
30 DType::Float64 | DType::Int64 | DType::UInt64 => 8,
31 }
32 }
33
34 pub fn name(self) -> &'static str {
36 match self {
37 DType::Float16 => "float16",
38 DType::Float32 => "float32",
39 DType::Float64 => "float64",
40 DType::Int8 => "int8",
41 DType::Int16 => "int16",
42 DType::Int32 => "int32",
43 DType::Int64 => "int64",
44 DType::UInt8 => "uint8",
45 DType::UInt16 => "uint16",
46 DType::UInt32 => "uint32",
47 DType::UInt64 => "uint64",
48 }
49 }
50
51 pub fn parse(s: &str) -> Result<Self> {
53 match s {
54 "float16" => Ok(DType::Float16),
55 "float32" => Ok(DType::Float32),
56 "float64" => Ok(DType::Float64),
57 "int8" => Ok(DType::Int8),
58 "int16" => Ok(DType::Int16),
59 "int32" => Ok(DType::Int32),
60 "int64" => Ok(DType::Int64),
61 "uint8" => Ok(DType::UInt8),
62 "uint16" => Ok(DType::UInt16),
63 "uint32" => Ok(DType::UInt32),
64 "uint64" => Ok(DType::UInt64),
65 _ => Err(TrxError::DType(s.to_string())),
66 }
67 }
68
69 pub fn is_float(self) -> bool {
71 matches!(self, DType::Float16 | DType::Float32 | DType::Float64)
72 }
73}
74
75impl fmt::Display for DType {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 f.write_str(self.name())
78 }
79}
80
81pub trait TrxScalar: Pod + Zeroable + Copy + 'static + fmt::Debug {
86 const DTYPE: DType;
87
88 fn to_f32(self) -> f32;
90
91 fn to_f64(self) -> f64;
93}
94
95impl TrxScalar for f32 {
96 const DTYPE: DType = DType::Float32;
97 fn to_f32(self) -> f32 {
98 self
99 }
100 fn to_f64(self) -> f64 {
101 self as f64
102 }
103}
104
105impl TrxScalar for f64 {
106 const DTYPE: DType = DType::Float64;
107 fn to_f32(self) -> f32 {
108 self as f32
109 }
110 fn to_f64(self) -> f64 {
111 self
112 }
113}
114
115impl TrxScalar for f16 {
116 const DTYPE: DType = DType::Float16;
117 fn to_f32(self) -> f32 {
118 f16::to_f32(self)
119 }
120 fn to_f64(self) -> f64 {
121 f16::to_f64(self)
122 }
123}
124
125impl TrxScalar for i8 {
126 const DTYPE: DType = DType::Int8;
127 fn to_f32(self) -> f32 {
128 self as f32
129 }
130 fn to_f64(self) -> f64 {
131 self as f64
132 }
133}
134impl TrxScalar for i16 {
135 const DTYPE: DType = DType::Int16;
136 fn to_f32(self) -> f32 {
137 self as f32
138 }
139 fn to_f64(self) -> f64 {
140 self as f64
141 }
142}
143impl TrxScalar for i32 {
144 const DTYPE: DType = DType::Int32;
145 fn to_f32(self) -> f32 {
146 self as f32
147 }
148 fn to_f64(self) -> f64 {
149 self as f64
150 }
151}
152impl TrxScalar for i64 {
153 const DTYPE: DType = DType::Int64;
154 fn to_f32(self) -> f32 {
155 self as f32
156 }
157 fn to_f64(self) -> f64 {
158 self as f64
159 }
160}
161impl TrxScalar for u8 {
162 const DTYPE: DType = DType::UInt8;
163 fn to_f32(self) -> f32 {
164 self as f32
165 }
166 fn to_f64(self) -> f64 {
167 self as f64
168 }
169}
170impl TrxScalar for u16 {
171 const DTYPE: DType = DType::UInt16;
172 fn to_f32(self) -> f32 {
173 self as f32
174 }
175 fn to_f64(self) -> f64 {
176 self as f64
177 }
178}
179impl TrxScalar for u32 {
180 const DTYPE: DType = DType::UInt32;
181 fn to_f32(self) -> f32 {
182 self as f32
183 }
184 fn to_f64(self) -> f64 {
185 self as f64
186 }
187}
188impl TrxScalar for u64 {
189 const DTYPE: DType = DType::UInt64;
190 fn to_f32(self) -> f32 {
191 self as f32
192 }
193 fn to_f64(self) -> f64 {
194 self as f64
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn dtype_round_trip() {
204 for dt in [
205 DType::Float16,
206 DType::Float32,
207 DType::Float64,
208 DType::Int8,
209 DType::Int16,
210 DType::Int32,
211 DType::Int64,
212 DType::UInt8,
213 DType::UInt16,
214 DType::UInt32,
215 DType::UInt64,
216 ] {
217 assert_eq!(DType::parse(dt.name()).unwrap(), dt);
218 }
219 }
220
221 #[test]
222 fn dtype_sizes() {
223 assert_eq!(DType::Float32.size_of(), 4);
224 assert_eq!(DType::Float64.size_of(), 8);
225 assert_eq!(DType::Float16.size_of(), 2);
226 assert_eq!(DType::UInt8.size_of(), 1);
227 }
228
229 #[test]
230 fn dtype_parse_invalid() {
231 assert!(DType::parse("complex128").is_err());
232 }
233}