1use core::f32;
2
3use alloc::boxed::Box;
4use alloc::format;
5use alloc::string::String;
6use alloc::vec::Vec;
7use bytemuck::{AnyBitPattern, CheckedBitPattern, Zeroable, cast_mut, checked::CheckedCastError};
8use rand::Rng;
9use thiserror::Error;
10
11use crate::Scalar;
12use crate::distribution::Distribution;
13use crate::element::{Element, ElementConversion};
14use crate::tensor::DType;
15use crate::{
16 BoolStore, Bytes, QuantLevel, QuantMode, QuantScheme, QuantValue, QuantizedBytes, Shape, bf16,
17 f16,
18};
19
20use serde::{Deserialize, Serialize};
21
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
24pub struct TensorData {
25 pub bytes: Bytes,
27
28 #[serde(with = "shape_inner")]
30 pub shape: Shape,
31
32 pub dtype: DType,
34}
35
36mod shape_inner {
38 use crate::SmallVec;
39
40 use super::*;
41
42 pub fn serialize<S: serde::Serializer>(
43 shape: &Shape,
44 serializer: S,
45 ) -> Result<S::Ok, S::Error> {
46 shape.as_slice().serialize(serializer)
47 }
48
49 pub fn deserialize<'de, D: serde::Deserializer<'de>>(
50 deserializer: D,
51 ) -> Result<Shape, D::Error> {
52 let dims = SmallVec::<[usize; _]>::deserialize(deserializer)?;
53 Ok(Shape::new_raw(dims))
54 }
55}
56
57impl TensorData {
58 pub fn new<E: Element, S: Into<Shape>>(value: Vec<E>, shape: S) -> Self {
60 let shape = shape.into();
62 Self::check_data_len(&value, &shape);
63
64 Self {
65 bytes: Bytes::from_elems(value),
66 shape,
67 dtype: E::dtype(),
68 }
69 }
70
71 pub fn quantized<E: Element, S: Into<Shape>>(
73 value: Vec<E>,
74 shape: S,
75 scheme: QuantScheme,
76 qparams: &[f32],
77 ) -> Self {
78 let shape = shape.into();
79 Self::check_data_len(&value, &shape);
80
81 let q_bytes = QuantizedBytes::new(value, scheme, qparams);
82
83 Self {
84 bytes: q_bytes.bytes,
85 shape,
86 dtype: DType::QFloat(q_bytes.scheme),
87 }
88 }
89
90 pub fn from_bytes<S: Into<Shape>>(bytes: Bytes, shape: S, dtype: DType) -> Self {
92 Self {
93 bytes,
94 shape: shape.into(),
95 dtype,
96 }
97 }
98
99 pub fn from_bytes_vec<S: Into<Shape>>(bytes: Vec<u8>, shape: S, dtype: DType) -> Self {
104 Self {
105 bytes: Bytes::from_bytes_vec(bytes),
106 shape: shape.into(),
107 dtype,
108 }
109 }
110
111 fn check_data_len<E: Element>(data: &[E], shape: &Shape) {
113 let expected_data_len = Self::numel(shape);
114 let num_data = data.len();
115 assert_eq!(
116 expected_data_len, num_data,
117 "Shape {shape:?} is invalid for input of size {num_data:?}",
118 );
119 }
120
121 pub fn as_slice<E: Element>(&self) -> Result<&[E], DataError> {
123 if self.matches_target_dtype::<E>() {
124 match E::dtype() {
125 DType::Bool(BoolStore::Native) => {
129 let slice = bytemuck::checked::try_cast_slice::<_, u8>(&self.bytes)
130 .map_err(DataError::CastError)?;
131 Ok(unsafe { core::mem::transmute::<&[u8], &[E]>(slice) })
132 }
133 _ => bytemuck::checked::try_cast_slice(&self.bytes).map_err(DataError::CastError),
134 }
135 } else {
136 Err(DataError::TypeMismatch(format!(
137 "Invalid target element type (expected {:?}, got {:?})",
138 self.dtype,
139 E::dtype()
140 )))
141 }
142 }
143
144 pub fn as_mut_slice<E: Element>(&mut self) -> Result<&mut [E], DataError> {
149 if self.matches_target_dtype::<E>() {
150 match E::dtype() {
151 DType::Bool(BoolStore::Native) => {
155 let slice = bytemuck::checked::try_cast_slice_mut::<_, u8>(&mut self.bytes)
156 .map_err(DataError::CastError)?;
157 Ok(unsafe { core::mem::transmute::<&mut [u8], &mut [E]>(slice) })
158 }
159 _ => bytemuck::checked::try_cast_slice_mut(&mut self.bytes)
160 .map_err(DataError::CastError),
161 }
162 } else {
163 Err(DataError::TypeMismatch(format!(
164 "Invalid target element type (expected {:?}, got {:?})",
165 self.dtype,
166 E::dtype()
167 )))
168 }
169 }
170
171 pub fn to_vec<E: Element>(&self) -> Result<Vec<E>, DataError> {
173 Ok(self.as_slice()?.to_vec())
174 }
175
176 pub fn into_vec<E: Element>(self) -> Result<Vec<E>, DataError> {
178 if !self.matches_target_dtype::<E>() {
180 return Err(DataError::TypeMismatch(format!(
181 "Invalid target element type (expected {:?}, got {:?})",
182 self.dtype,
183 E::dtype()
184 )));
185 }
186
187 match E::dtype() {
188 DType::Bool(BoolStore::Native) => {
192 let vec = self.into_vec_unchecked::<u8>()?;
193 Ok(unsafe { core::mem::transmute::<Vec<u8>, Vec<E>>(vec) })
194 }
195 _ => self.into_vec_unchecked(),
196 }
197 }
198
199 fn into_vec_unchecked<E: Element>(self) -> Result<Vec<E>, DataError> {
201 let mut me = self;
202 me.bytes = match me.bytes.try_into_vec::<E>() {
203 Ok(elems) => return Ok(elems),
204 Err(bytes) => bytes,
205 };
206
207 Ok(bytemuck::checked::try_cast_slice(me.as_bytes())
210 .map_err(DataError::CastError)?
211 .to_vec())
212 }
213
214 fn matches_target_dtype<E: Element>(&self) -> bool {
215 let target_dtype = E::dtype();
216 match self.dtype {
217 DType::Bool(BoolStore::U8) => {
218 matches!(target_dtype, DType::U8 | DType::Bool(BoolStore::U8))
219 }
220 DType::Bool(BoolStore::U32) => {
221 matches!(target_dtype, DType::U32 | DType::Bool(BoolStore::U32))
222 }
223 dtype => dtype == target_dtype,
224 }
225 }
226
227 pub fn iter<E: Element>(&self) -> Box<dyn Iterator<Item = E> + '_> {
229 if E::dtype() == self.dtype {
230 Box::new(bytemuck::checked::cast_slice(&self.bytes).iter().copied())
231 } else {
232 match self.dtype {
233 DType::I8 => Box::new(
234 bytemuck::checked::cast_slice(&self.bytes)
235 .iter()
236 .map(|e: &i8| e.elem::<E>()),
237 ),
238 DType::I16 => Box::new(
239 bytemuck::checked::cast_slice(&self.bytes)
240 .iter()
241 .map(|e: &i16| e.elem::<E>()),
242 ),
243 DType::I32 => Box::new(
244 bytemuck::checked::cast_slice(&self.bytes)
245 .iter()
246 .map(|e: &i32| e.elem::<E>()),
247 ),
248 DType::I64 => Box::new(
249 bytemuck::checked::cast_slice(&self.bytes)
250 .iter()
251 .map(|e: &i64| e.elem::<E>()),
252 ),
253 DType::U8 => Box::new(self.bytes.iter().map(|e| e.elem::<E>())),
254 DType::U16 => Box::new(
255 bytemuck::checked::cast_slice(&self.bytes)
256 .iter()
257 .map(|e: &u16| e.elem::<E>()),
258 ),
259 DType::U32 => Box::new(
260 bytemuck::checked::cast_slice(&self.bytes)
261 .iter()
262 .map(|e: &u32| e.elem::<E>()),
263 ),
264 DType::U64 => Box::new(
265 bytemuck::checked::cast_slice(&self.bytes)
266 .iter()
267 .map(|e: &u64| e.elem::<E>()),
268 ),
269 DType::BF16 => Box::new(
270 bytemuck::checked::cast_slice(&self.bytes)
271 .iter()
272 .map(|e: &bf16| e.elem::<E>()),
273 ),
274 DType::F16 => Box::new(
275 bytemuck::checked::cast_slice(&self.bytes)
276 .iter()
277 .map(|e: &f16| e.elem::<E>()),
278 ),
279 DType::F32 | DType::Flex32 => Box::new(
280 bytemuck::checked::cast_slice(&self.bytes)
281 .iter()
282 .map(|e: &f32| e.elem::<E>()),
283 ),
284 DType::F64 => Box::new(
285 bytemuck::checked::cast_slice(&self.bytes)
286 .iter()
287 .map(|e: &f64| e.elem::<E>()),
288 ),
289 DType::Bool(BoolStore::Native) | DType::Bool(BoolStore::U8) => {
291 Box::new(self.bytes.iter().map(|e| e.elem::<E>()))
292 }
293 DType::Bool(BoolStore::U32) => Box::new(
294 bytemuck::checked::cast_slice(&self.bytes)
295 .iter()
296 .map(|e: &u32| e.elem::<E>()),
297 ),
298 DType::QFloat(scheme) => match scheme {
299 QuantScheme {
300 level: QuantLevel::Tensor | QuantLevel::Block(_),
301 mode: QuantMode::Symmetric,
302 value:
303 QuantValue::Q8F
304 | QuantValue::Q8S
305 | QuantValue::Q4F
307 | QuantValue::Q4S
308 | QuantValue::Q2F
309 | QuantValue::Q2S,
310 ..
311 } => {
312 let q_bytes = QuantizedBytes {
314 bytes: self.bytes.clone(),
315 scheme,
316 num_elements: self.num_elements(),
317 };
318 let (values, _) = q_bytes.into_vec_i8();
319
320 Box::new(
321 values
322 .iter()
323 .map(|e: &i8| e.elem::<E>())
324 .collect::<Vec<_>>()
325 .into_iter(),
326 )
327 }
328 QuantScheme {
329 level: QuantLevel::Tensor | QuantLevel::Block(_),
330 mode: QuantMode::Symmetric,
331 value:
332 QuantValue::E4M3 | QuantValue::E5M2 | QuantValue::E2M1,
333 ..
334 } => {
335 unimplemented!("Not yet implemented for iteration");
336 }
337 QuantScheme {
338 level: QuantLevel::BlockTensor { .. },
339 ..
340 } => {
341 unimplemented!("two-level quantization is not supported yet")
342 }
343 },
344 }
345 }
346 }
347
348 pub fn rank(&self) -> usize {
350 self.shape.len()
351 }
352
353 pub fn num_elements(&self) -> usize {
355 Self::numel(&self.shape)
356 }
357
358 fn numel(shape: &[usize]) -> usize {
359 shape.iter().product()
360 }
361
362 pub fn random<E: Element, R: Rng, S: Into<Shape>>(
364 shape: S,
365 distribution: Distribution,
366 rng: &mut R,
367 ) -> Self {
368 let shape = shape.into();
369 let num_elements = Self::numel(&shape);
370 let mut data = Vec::with_capacity(num_elements);
371
372 for _ in 0..num_elements {
373 data.push(E::random(distribution, rng));
374 }
375
376 TensorData::new(data, shape)
377 }
378
379 pub fn zeros<E: Element, S: Into<Shape>>(shape: S) -> TensorData {
381 let shape = shape.into();
382 let num_elements = Self::numel(&shape);
383 let mut data = Vec::<E>::with_capacity(num_elements);
384
385 for _ in 0..num_elements {
386 data.push(0.elem());
387 }
388
389 TensorData::new(data, shape)
390 }
391
392 pub fn ones<E: Element, S: Into<Shape>>(shape: S) -> TensorData {
394 let shape = shape.into();
395 let num_elements = Self::numel(&shape);
396 let mut data = Vec::<E>::with_capacity(num_elements);
397
398 for _ in 0..num_elements {
399 data.push(1.elem());
400 }
401
402 TensorData::new(data, shape)
403 }
404
405 pub fn full<E: Element, S: Into<Shape>>(shape: S, fill_value: E) -> TensorData {
407 let shape = shape.into();
408 let num_elements = Self::numel(&shape);
409 let mut data = Vec::<E>::with_capacity(num_elements);
410 for _ in 0..num_elements {
411 data.push(fill_value)
412 }
413
414 TensorData::new(data, shape)
415 }
416
417 pub fn full_dtype<E: Into<Scalar>, S: Into<Shape>>(
419 shape: S,
420 fill_value: E,
421 dtype: DType,
422 ) -> TensorData {
423 let fill_value = fill_value.into();
424 match dtype {
425 DType::F64 => Self::full::<f64, _>(shape, fill_value.elem()),
426 DType::F32 | DType::Flex32 => Self::full::<f32, _>(shape, fill_value.elem()),
427 DType::F16 => Self::full::<f16, _>(shape, fill_value.elem()),
428 DType::BF16 => Self::full::<bf16, _>(shape, fill_value.elem()),
429 DType::I64 => Self::full::<i64, _>(shape, fill_value.elem()),
430 DType::I32 => Self::full::<i32, _>(shape, fill_value.elem()),
431 DType::I16 => Self::full::<i16, _>(shape, fill_value.elem()),
432 DType::I8 => Self::full::<i8, _>(shape, fill_value.elem()),
433 DType::U64 => Self::full::<u64, _>(shape, fill_value.elem()),
434 DType::U32 => Self::full::<u32, _>(shape, fill_value.elem()),
435 DType::U16 => Self::full::<u16, _>(shape, fill_value.elem()),
436 DType::U8 => Self::full::<u8, _>(shape, fill_value.elem()),
437 DType::Bool(BoolStore::Native) => Self::full::<bool, _>(shape, fill_value.elem()),
438 DType::Bool(BoolStore::U8) => {
439 Self::full::<u8, _>(shape, fill_value.elem()).into_bool_u8()
440 }
441 DType::Bool(BoolStore::U32) => {
442 Self::full::<u32, _>(shape, fill_value.elem()).into_bool_u32()
443 }
444 DType::QFloat(_) => unreachable!(),
445 }
446 }
447
448 fn into_bool_u8(mut self) -> Self {
450 self.dtype = DType::Bool(BoolStore::U8);
451 self
452 }
453
454 fn into_bool_u32(mut self) -> Self {
456 self.dtype = DType::Bool(BoolStore::U32);
457 self
458 }
459
460 pub fn convert<E: Element>(self) -> Self {
462 self.convert_dtype(E::dtype())
463 }
464
465 pub fn convert_dtype(self, dtype: DType) -> Self {
467 if dtype == self.dtype {
468 self
469 } else if dtype.size() == self.dtype.size()
470 && !matches!(
471 self.dtype,
472 DType::Bool(BoolStore::Native) | DType::QFloat(_)
473 )
474 && !matches!(dtype, DType::Bool(BoolStore::Native) | DType::QFloat(_))
475 {
476 match self.dtype {
477 DType::F64 => self.convert_inplace_dtype::<f64>(dtype),
478 DType::F32 | DType::Flex32 => self.convert_inplace_dtype::<f32>(dtype),
479 DType::F16 => self.convert_inplace_dtype::<f16>(dtype),
480 DType::BF16 => self.convert_inplace_dtype::<bf16>(dtype),
481 DType::I64 => self.convert_inplace_dtype::<i64>(dtype),
482 DType::I32 => self.convert_inplace_dtype::<i32>(dtype),
483 DType::I16 => self.convert_inplace_dtype::<i16>(dtype),
484 DType::I8 => self.convert_inplace_dtype::<i8>(dtype),
485 DType::U64 => self.convert_inplace_dtype::<u64>(dtype),
486 DType::U32 => self.convert_inplace_dtype::<u32>(dtype),
487 DType::U16 => self.convert_inplace_dtype::<u16>(dtype),
488 DType::U8 => self.convert_inplace_dtype::<u8>(dtype),
489 DType::Bool(BoolStore::U8) => self.convert_inplace_dtype::<u8>(dtype),
490 DType::Bool(BoolStore::U32) => self.convert_inplace_dtype::<u32>(dtype),
491 DType::Bool(BoolStore::Native) | DType::QFloat(_) => unreachable!(),
492 }
493 } else {
494 match self.dtype {
495 DType::F64 => self.convert_clone_dtype::<f64>(dtype),
496 DType::F32 | DType::Flex32 => self.convert_clone_dtype::<f32>(dtype),
497 DType::F16 => self.convert_clone_dtype::<f16>(dtype),
498 DType::BF16 => self.convert_clone_dtype::<bf16>(dtype),
499 DType::I64 => self.convert_clone_dtype::<i64>(dtype),
500 DType::I32 => self.convert_clone_dtype::<i32>(dtype),
501 DType::I16 => self.convert_clone_dtype::<i16>(dtype),
502 DType::I8 => self.convert_clone_dtype::<i8>(dtype),
503 DType::U64 => self.convert_clone_dtype::<u64>(dtype),
504 DType::U32 => self.convert_clone_dtype::<u32>(dtype),
505 DType::U16 => self.convert_clone_dtype::<u16>(dtype),
506 DType::U8 => self.convert_clone_dtype::<u8>(dtype),
507 DType::Bool(BoolStore::Native) => self.convert_clone_dtype::<bool>(dtype),
508 DType::Bool(BoolStore::U8) => self.convert_clone_dtype::<u8>(dtype),
509 DType::Bool(BoolStore::U32) => self.convert_clone_dtype::<u32>(dtype),
510 DType::QFloat(_) => unreachable!(),
511 }
512 }
513 }
514
515 fn convert_inplace_dtype<Current: Element + AnyBitPattern>(self, dtype: DType) -> Self {
516 match dtype {
517 DType::F64 => self.convert_inplace::<Current, f64>(),
518 DType::F32 | DType::Flex32 => self.convert_inplace::<Current, f32>(),
519 DType::F16 => self.convert_inplace::<Current, f16>(),
520 DType::BF16 => self.convert_inplace::<Current, bf16>(),
521 DType::I64 => self.convert_inplace::<Current, i64>(),
522 DType::I32 => self.convert_inplace::<Current, i32>(),
523 DType::I16 => self.convert_inplace::<Current, i16>(),
524 DType::I8 => self.convert_inplace::<Current, i8>(),
525 DType::U64 => self.convert_inplace::<Current, u64>(),
526 DType::U32 => self.convert_inplace::<Current, u32>(),
527 DType::U16 => self.convert_inplace::<Current, u16>(),
528 DType::U8 => self.convert_inplace::<Current, u8>(),
529 DType::Bool(BoolStore::U8) => self.convert_inplace_bool::<Current, u8>().into_bool_u8(),
530 DType::Bool(BoolStore::U32) => {
531 self.convert_inplace_bool::<Current, u32>().into_bool_u32()
532 }
533 DType::Bool(BoolStore::Native) | DType::QFloat(_) => unreachable!(),
534 }
535 }
536
537 fn convert_inplace<Current: Element + AnyBitPattern, Target: Element + AnyBitPattern>(
538 self,
539 ) -> Self {
540 self.convert_inplace_with::<Current, Target>(|x| x.elem())
541 }
542
543 fn convert_inplace_bool<Current: Element + AnyBitPattern, Target: Element + AnyBitPattern>(
544 self,
545 ) -> Self {
546 self.convert_inplace_with::<Current, Target>(|x| x.to_bool().elem())
547 }
548
549 fn convert_inplace_with<Current: Element + AnyBitPattern, Target: Element + AnyBitPattern>(
550 mut self,
551 transform: impl Fn(&Current) -> Target,
552 ) -> Self {
553 for x in bytemuck::cast_slice_mut::<_, Current>(&mut self.bytes) {
554 let t = transform(x);
555 let x = cast_mut::<_, Target>(x);
556 *x = t;
557 }
558
559 self.dtype = Target::dtype();
560
561 self
562 }
563
564 fn convert_clone_dtype<Current: Element + CheckedBitPattern>(self, dtype: DType) -> Self {
565 match dtype {
566 DType::F64 => self.convert_clone::<Current, f64>(),
567 DType::F32 | DType::Flex32 => self.convert_clone::<Current, f32>(),
568 DType::F16 => self.convert_clone::<Current, f16>(),
569 DType::BF16 => self.convert_clone::<Current, bf16>(),
570 DType::I64 => self.convert_clone::<Current, i64>(),
571 DType::I32 => self.convert_clone::<Current, i32>(),
572 DType::I16 => self.convert_clone::<Current, i16>(),
573 DType::I8 => self.convert_clone::<Current, i8>(),
574 DType::U64 => self.convert_clone::<Current, u64>(),
575 DType::U32 => self.convert_clone::<Current, u32>(),
576 DType::U16 => self.convert_clone::<Current, u16>(),
577 DType::U8 => self.convert_clone::<Current, u8>(),
578 DType::Bool(BoolStore::Native) => self.convert_clone::<Current, bool>(),
579 DType::Bool(BoolStore::U8) => self.convert_clone_bool::<Current, u8>().into_bool_u8(),
580 DType::Bool(BoolStore::U32) => {
581 self.convert_clone_bool::<Current, u32>().into_bool_u32()
582 }
583 DType::QFloat(_) => unreachable!(),
584 }
585 }
586
587 fn convert_clone<Current: Element + CheckedBitPattern, Target: Element + Zeroable>(
588 self,
589 ) -> Self {
590 self.convert_clone_with::<Current, Target>(|x| x.elem())
591 }
592
593 fn convert_clone_bool<Current: Element + CheckedBitPattern, Target: Element + Zeroable>(
594 self,
595 ) -> Self {
596 self.convert_clone_with::<Current, Target>(|x| x.to_bool().elem())
597 }
598
599 fn convert_clone_with<Current: Element + CheckedBitPattern, Target: Element + Zeroable>(
600 self,
601 transform: impl Fn(&Current) -> Target,
602 ) -> Self {
603 let this = bytemuck::checked::cast_slice::<_, Current>(&self.bytes);
604 let mut out: Vec<Target> = ::alloc::vec![Zeroable::zeroed(); self.num_elements()];
605
606 for (x, out) in this.iter().zip(&mut out) {
607 *out = transform(x);
608 }
609
610 Self::new(out, self.shape)
611 }
612
613 pub fn as_bytes(&self) -> &[u8] {
615 &self.bytes
616 }
617
618 pub fn into_bytes(self) -> Bytes {
620 self.bytes
621 }
622}
623
624impl<E: Element, const A: usize> From<[E; A]> for TensorData {
625 fn from(elems: [E; A]) -> Self {
626 TensorData::new(elems.to_vec(), [A])
627 }
628}
629
630impl<const A: usize> From<[usize; A]> for TensorData {
631 fn from(elems: [usize; A]) -> Self {
632 TensorData::new(elems.iter().map(|&e| e as i64).collect(), [A])
633 }
634}
635
636impl From<&[usize]> for TensorData {
637 fn from(elems: &[usize]) -> Self {
638 let mut data = Vec::with_capacity(elems.len());
639 for elem in elems.iter() {
640 data.push(*elem as i64);
641 }
642
643 TensorData::new(data, [elems.len()])
644 }
645}
646
647impl<E: Element> From<&[E]> for TensorData {
648 fn from(elems: &[E]) -> Self {
649 let mut data = Vec::with_capacity(elems.len());
650 for elem in elems.iter() {
651 data.push(*elem);
652 }
653
654 TensorData::new(data, [elems.len()])
655 }
656}
657
658impl<E: Element, const A: usize, const B: usize> From<[[E; B]; A]> for TensorData {
659 fn from(elems: [[E; B]; A]) -> Self {
660 let mut data = Vec::with_capacity(A * B);
661 for elem in elems.into_iter().take(A) {
662 for elem in elem.into_iter().take(B) {
663 data.push(elem);
664 }
665 }
666
667 TensorData::new(data, [A, B])
668 }
669}
670
671impl<E: Element, const A: usize, const B: usize, const C: usize> From<[[[E; C]; B]; A]>
672 for TensorData
673{
674 fn from(elems: [[[E; C]; B]; A]) -> Self {
675 let mut data = Vec::with_capacity(A * B * C);
676
677 for elem in elems.into_iter().take(A) {
678 for elem in elem.into_iter().take(B) {
679 for elem in elem.into_iter().take(C) {
680 data.push(elem);
681 }
682 }
683 }
684
685 TensorData::new(data, [A, B, C])
686 }
687}
688
689impl<E: Element, const A: usize, const B: usize, const C: usize, const D: usize>
690 From<[[[[E; D]; C]; B]; A]> for TensorData
691{
692 fn from(elems: [[[[E; D]; C]; B]; A]) -> Self {
693 let mut data = Vec::with_capacity(A * B * C * D);
694
695 for elem in elems.into_iter().take(A) {
696 for elem in elem.into_iter().take(B) {
697 for elem in elem.into_iter().take(C) {
698 for elem in elem.into_iter().take(D) {
699 data.push(elem);
700 }
701 }
702 }
703 }
704
705 TensorData::new(data, [A, B, C, D])
706 }
707}
708
709impl<Elem: Element, const A: usize, const B: usize, const C: usize, const D: usize, const E: usize>
710 From<[[[[[Elem; E]; D]; C]; B]; A]> for TensorData
711{
712 fn from(elems: [[[[[Elem; E]; D]; C]; B]; A]) -> Self {
713 let mut data = Vec::with_capacity(A * B * C * D * E);
714
715 for elem in elems.into_iter().take(A) {
716 for elem in elem.into_iter().take(B) {
717 for elem in elem.into_iter().take(C) {
718 for elem in elem.into_iter().take(D) {
719 for elem in elem.into_iter().take(E) {
720 data.push(elem);
721 }
722 }
723 }
724 }
725 }
726
727 TensorData::new(data, [A, B, C, D, E])
728 }
729}
730impl core::fmt::Display for TensorData {
731 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
732 let fmt = match self.dtype {
733 DType::F64 => format!("{:?}", self.as_slice::<f64>().unwrap()),
734 DType::F32 | DType::Flex32 => format!("{:?}", self.as_slice::<f32>().unwrap()),
735 DType::F16 => format!("{:?}", self.as_slice::<f16>().unwrap()),
736 DType::BF16 => format!("{:?}", self.as_slice::<bf16>().unwrap()),
737 DType::I64 => format!("{:?}", self.as_slice::<i64>().unwrap()),
738 DType::I32 => format!("{:?}", self.as_slice::<i32>().unwrap()),
739 DType::I16 => format!("{:?}", self.as_slice::<i16>().unwrap()),
740 DType::I8 => format!("{:?}", self.as_slice::<i8>().unwrap()),
741 DType::U64 => format!("{:?}", self.as_slice::<u64>().unwrap()),
742 DType::U32 => format!("{:?}", self.as_slice::<u32>().unwrap()),
743 DType::U16 => format!("{:?}", self.as_slice::<u16>().unwrap()),
744 DType::U8 => format!("{:?}", self.as_slice::<u8>().unwrap()),
745 DType::Bool(BoolStore::Native) => format!("{:?}", self.as_slice::<bool>().unwrap()),
746 DType::Bool(BoolStore::U8) => format!("{:?}", self.as_slice::<u8>().unwrap()),
747 DType::Bool(BoolStore::U32) => format!("{:?}", self.as_slice::<u32>().unwrap()),
748 DType::QFloat(scheme) => match scheme {
749 QuantScheme {
750 level: QuantLevel::Tensor | QuantLevel::Block(_),
751 mode: QuantMode::Symmetric,
752 value:
753 QuantValue::Q8F
754 | QuantValue::Q8S
755 | QuantValue::Q4F
757 | QuantValue::Q4S
758 | QuantValue::Q2F
759 | QuantValue::Q2S,
760 ..
761 } => {
762 format!("{:?} {scheme:?}", self.iter::<i8>().collect::<Vec<_>>())
763 },
764 QuantScheme {
765 level: QuantLevel::Tensor | QuantLevel::Block(_),
766 mode: QuantMode::Symmetric,
767 value:
768 QuantValue::E4M3 | QuantValue::E5M2 | QuantValue::E2M1,
769 ..
770 } => {
771 unimplemented!("Can't format yet");
772 }
773 QuantScheme {
774 level: QuantLevel::BlockTensor { .. },
775 ..
776 } => {
777 unimplemented!("two-level quantization is not supported yet")
778 }
779 },
780 };
781 f.write_str(fmt.as_str())
782 }
783}
784
785#[derive(Debug, Error)]
787pub enum DataError {
788 #[error("Failed to cast values to the specified element type.\nError:\n {0}")]
790 CastError(CheckedCastError),
791 #[error("{0}")]
793 TypeMismatch(String),
794}
795
796#[cfg(test)]
797mod tests {
798 use super::*;
799 use crate::shape;
800 use alloc::vec;
801 use rand::{
802 SeedableRng,
803 rngs::{StdRng, SysRng},
804 };
805
806 #[test]
807 fn should_have_rank() {
808 let shape = [3, 5, 6];
809 let data = TensorData::random::<f32, _, _>(
810 shape,
811 Distribution::Default,
812 &mut StdRng::try_from_rng(&mut SysRng).unwrap(),
813 );
814
815 assert_eq!(data.rank(), 3);
816 }
817
818 #[test]
819 fn into_vec_should_yield_same_value_as_iter() {
820 let shape = [3, 5, 6];
821 let data = TensorData::random::<f32, _, _>(
822 shape,
823 Distribution::Default,
824 &mut StdRng::try_from_rng(&mut SysRng).unwrap(),
825 );
826
827 let expected = data.iter::<f32>().collect::<Vec<f32>>();
828 let actual = data.into_vec::<f32>().unwrap();
829
830 assert_eq!(expected, actual);
831 }
832
833 #[test]
834 #[should_panic]
835 fn into_vec_should_assert_wrong_dtype() {
836 let shape = [3, 5, 6];
837 let data = TensorData::random::<f32, _, _>(
838 shape,
839 Distribution::Default,
840 &mut StdRng::try_from_rng(&mut SysRng).unwrap(),
841 );
842
843 data.into_vec::<i32>().unwrap();
844 }
845
846 #[test]
847 fn should_have_right_num_elements() {
848 let shape = [3, 5, 6];
849 let num_elements: usize = shape.iter().product();
850 let data = TensorData::random::<f32, _, _>(
851 shape,
852 Distribution::Default,
853 &mut StdRng::try_from_rng(&mut SysRng).unwrap(),
854 );
855
856 assert_eq!(num_elements, data.bytes.len() / 4); assert_eq!(num_elements, data.as_slice::<f32>().unwrap().len());
858 }
859
860 #[test]
861 fn should_have_right_shape() {
862 let data = TensorData::from([[3.0, 5.0, 6.0]]);
863 assert_eq!(data.shape, shape![1, 3]);
864
865 let data = TensorData::from([[4.0, 5.0, 8.0], [3.0, 5.0, 6.0]]);
866 assert_eq!(data.shape, shape![2, 3]);
867
868 let data = TensorData::from([3.0, 5.0, 6.0]);
869 assert_eq!(data.shape, shape![3]);
870 }
871
872 #[test]
873 fn should_convert_bytes_correctly() {
874 let mut vector: Vec<f32> = Vec::with_capacity(5);
875 vector.push(2.0);
876 vector.push(3.0);
877 let data1 = TensorData::new(vector, vec![2]);
878
879 let factor = core::mem::size_of::<f32>() / core::mem::size_of::<u8>();
880 assert_eq!(data1.bytes.len(), 2 * factor);
881 assert_eq!(data1.bytes.capacity(), 5 * factor);
882 }
883
884 #[test]
885 fn should_convert_bytes_correctly_inplace() {
886 fn test_precision<E: Element>() {
887 let data = TensorData::new((0..32).collect(), [32]);
888 for (i, val) in data
889 .clone()
890 .convert::<E>()
891 .into_vec::<E>()
892 .unwrap()
893 .into_iter()
894 .enumerate()
895 {
896 assert_eq!(i as u32, val.elem::<u32>())
897 }
898 }
899 test_precision::<f32>();
900 test_precision::<f16>();
901 test_precision::<i64>();
902 test_precision::<i32>();
903 }
904
905 #[test]
906 fn should_convert_negative_values_to_bool_store() {
907 for store in [BoolStore::U8, BoolStore::U32, BoolStore::Native] {
908 let data = TensorData::from([-1i32, 0, 1, -12]).convert_dtype(DType::Bool(store));
909 assert_eq!(data.dtype, DType::Bool(store));
910 assert_eq!(
911 data.iter::<bool>().collect::<Vec<_>>(),
912 [true, false, true, true]
913 );
914
915 let data = TensorData::from([-1.5f32, 0.0, 0.5]).convert_dtype(DType::Bool(store));
916 assert_eq!(data.iter::<bool>().collect::<Vec<_>>(), [true, false, true]);
917 }
918 }
919
920 macro_rules! test_dtypes {
921 ($test_name:ident, $($dtype:ty),*) => {
922 $(
923 paste::paste! {
924 #[test]
925 fn [<$test_name _ $dtype:snake>]() {
926 let full_dtype = TensorData::full_dtype([2, 16], 4, <$dtype>::dtype());
927 let full = TensorData::full::<$dtype, _>([2, 16], 4.elem());
928 assert_eq!(full_dtype, full);
929 }
930 }
931 )*
932 };
933}
934
935 test_dtypes!(
936 should_create_with_dtype,
937 bool,
938 i8,
939 i16,
940 i32,
941 i64,
942 u8,
943 u16,
944 u32,
945 u64,
946 f16,
947 bf16,
948 f32,
949 f64
950 );
951
952 #[test]
953 fn should_serialize_deserialize_tensor_data() {
954 let data = TensorData::new(vec![1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0], [2, 3]);
955 assert_eq!(
956 data.as_bytes(),
957 [
958 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192,
959 64
960 ]
961 );
962 let serialized = serde_json::to_string(&data).unwrap();
963 let deserialized: TensorData = serde_json::from_str(&serialized).unwrap();
964 assert_eq!(data, deserialized);
965 }
966
967 #[test]
968 fn should_deserialize_tensor_data_with_shape_inner() {
969 let serialized = r#"{
971 "bytes": [0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 128, 64, 0, 0, 160, 64, 0, 0, 192, 64],
972 "shape": [2, 3],
973 "dtype": "F32"
974 }"#;
975
976 let data: TensorData = serde_json::from_str(serialized).unwrap();
977 assert_eq!(data.shape, shape![2, 3]);
978 assert_eq!(
979 data.as_slice::<f32>().unwrap(),
980 &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
981 );
982 }
983
984 #[test]
985 fn should_serialize_shape_as_flat_array() {
986 let data = TensorData::new(vec![1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0], [2, 3]);
989 let serialized = serde_json::to_string(&data).unwrap();
990 let json: serde_json::Value = serde_json::from_str(&serialized).unwrap();
991 assert_eq!(json["shape"], serde_json::json!([2, 3]));
992 }
993}