1use crate::{
7 Bool, DTypeKind, Device, Float, FloatMeta, Int, Tensor,
8 dtype::{BoolDType, FloatDType, IntDType},
9};
10
11pub trait Cast<D: Device, K: DTypeKind<D>> {
12 type Output: DTypeKind<D>;
13 fn cast(tensor: &Tensor<D, K>, dtype: Self) -> crate::Result<Tensor<D, Self::Output>>;
14}
15
16impl<D: Device, K: DTypeKind<D>> Tensor<D, K> {
17 pub fn cast<T: Cast<D, K>>(&self, dtype: T) -> crate::Result<Tensor<D, T::Output>> {
18 T::cast(self, dtype)
19 }
20}
21
22impl<D: Device, K: CastDTypeKind<D>> Cast<D, K> for FloatDType {
23 type Output = Float;
24 fn cast(tensor: &Tensor<D, K>, dtype: Self) -> crate::Result<Tensor<D, Self::Output>> {
25 tensor.cast_float(dtype)
26 }
27}
28
29impl<D: Device, K: CastDTypeKind<D>> Cast<D, K> for IntDType {
30 type Output = Int;
31 fn cast(tensor: &Tensor<D, K>, dtype: Self) -> crate::Result<Tensor<D, Self::Output>> {
32 tensor.cast_int(dtype)
33 }
34}
35
36impl<D: Device, K: CastDTypeKind<D>> Cast<D, K> for BoolDType {
37 type Output = Bool;
38 fn cast(tensor: &Tensor<D, K>, dtype: Self) -> crate::Result<Tensor<D, Self::Output>> {
39 tensor.cast_bool(dtype)
40 }
41}
42
43pub trait CastDTypeKind<D: Device>: DTypeKind<D> {
44 fn cast_float(tensor: &Tensor<D, Self>, to: FloatDType) -> crate::Result<Tensor<D, Float>>;
45 fn cast_int(tensor: &Tensor<D, Self>, to: IntDType) -> crate::Result<Tensor<D, Int>>;
46 fn cast_bool(tensor: &Tensor<D, Self>, to: BoolDType) -> crate::Result<Tensor<D, Bool>>;
47}
48
49impl<D: Device> CastDTypeKind<D> for Float {
50 fn cast_float(tensor: &Tensor<D, Self>, to: FloatDType) -> crate::Result<Tensor<D, Float>> {
51 let storage = D::f_cast_float(&*tensor.storage_read()?, tensor.layout(), to)?;
52 let meta = FloatMeta::on_cast(tensor);
53 Ok(Tensor::from_storage(storage, tensor.shape().clone(), meta))
54 }
55
56 fn cast_int(tensor: &Tensor<D, Self>, to: IntDType) -> crate::Result<Tensor<D, Int>> {
57 let storage = D::f_cast_int(&*tensor.storage_read()?, tensor.layout(), to)?;
58 Ok(Tensor::from_storage(storage, tensor.shape().clone(), ()))
59 }
60
61 fn cast_bool(tensor: &Tensor<D, Self>, to: BoolDType) -> crate::Result<Tensor<D, Bool>> {
62 let storage = D::f_cast_bool(&*tensor.storage_read()?, tensor.layout(), to)?;
63 Ok(Tensor::from_storage(storage, tensor.shape().clone(), ()))
64 }
65}
66
67impl<D: Device> CastDTypeKind<D> for Int {
68 fn cast_float(tensor: &Tensor<D, Self>, to: FloatDType) -> crate::Result<Tensor<D, Float>> {
69 let storage = D::i_cast_float(&*tensor.storage_read()?, tensor.layout(), to)?;
70 Ok(Tensor::from_storage(storage, tensor.shape().clone(), FloatMeta::val()))
71 }
72
73 fn cast_int(tensor: &Tensor<D, Self>, to: IntDType) -> crate::Result<Tensor<D, Int>> {
74 let storage = D::i_cast_int(&*tensor.storage_read()?, tensor.layout(), to)?;
75 Ok(Tensor::from_storage(storage, tensor.shape().clone(), ()))
76 }
77
78 fn cast_bool(tensor: &Tensor<D, Self>, to: BoolDType) -> crate::Result<Tensor<D, Bool>> {
79 let storage = D::i_cast_bool(&*tensor.storage_read()?, tensor.layout(), to)?;
80 Ok(Tensor::from_storage(storage, tensor.shape().clone(), ()))
81 }
82}
83
84impl<D: Device> CastDTypeKind<D> for Bool {
85 fn cast_float(tensor: &Tensor<D, Self>, to: FloatDType) -> crate::Result<Tensor<D, Float>> {
86 let storage = D::b_cast_float(&*tensor.storage_read()?, tensor.layout(), to)?;
87 Ok(Tensor::from_storage(storage, tensor.shape().clone(), FloatMeta::val()))
88 }
89
90 fn cast_int(tensor: &Tensor<D, Self>, to: IntDType) -> crate::Result<Tensor<D, Int>> {
91 let storage = D::b_cast_int(&*tensor.storage_read()?, tensor.layout(), to)?;
92 Ok(Tensor::from_storage(storage, tensor.shape().clone(), ()))
93 }
94
95 fn cast_bool(tensor: &Tensor<D, Self>, to: BoolDType) -> crate::Result<Tensor<D, Bool>> {
96 let storage = D::b_cast_bool(&*tensor.storage_read()?, tensor.layout(), to)?;
97 Ok(Tensor::from_storage(storage, tensor.shape().clone(), ()))
98 }
99}
100
101impl<D: Device, K: CastDTypeKind<D>> Tensor<D, K> {
102 #[inline]
103 pub fn cast_float(&self, to: FloatDType) -> crate::Result<Tensor<D, Float>> {
104 K::cast_float(self, to)
105 }
106
107 #[inline]
108 pub fn cast_int(&self, to: IntDType) -> crate::Result<Tensor<D, Int>> {
109 K::cast_int(self, to)
110 }
111
112 #[inline]
113 pub fn cast_bool(&self, to: BoolDType) -> crate::Result<Tensor<D, Bool>> {
114 K::cast_bool(self, to)
115 }
116}