1use crate::dtype::{FloatDType, IntDType};
4use crate::{Bool, Device, Float, Int, Tensor};
5
6impl<D: Device> Tensor<D, Float> {
9 pub fn to_scalar(&self) -> crate::Result<f64> {
11 if self.element_count() != 1 {
12 return Err(crate::Error::NotScalar);
13 }
14 Ok(self.to_vec()?[0])
15 }
16}
17
18impl<D: Device> Tensor<D, Int> {
19 pub fn to_scalar(&self) -> crate::Result<i64> {
20 if self.element_count() != 1 {
21 return Err(crate::Error::NotScalar);
22 }
23 Ok(self.to_vec()?[0])
24 }
25}
26
27impl<D: Device> Tensor<D, Float> {
30 pub fn allclose(&self, other: &Self, rtol: f64, atol: f64) -> crate::Result<bool> {
31 if self.element_count() != other.element_count() {
32 return Ok(false);
33 }
34 D::f_allclose(&*self.storage_read()?, self.layout(), &*other.storage_read()?, other.layout(), rtol, atol)
35 }
36}
37
38impl<D: Device> Tensor<D, Int> {
39 pub fn allclose(&self, other: &Self) -> crate::Result<bool> {
40 if self.element_count() != other.element_count() {
41 return Ok(false);
42 }
43 D::i_allclose(&*self.storage_read()?, self.layout(), &*other.storage_read()?, other.layout())
44 }
45}
46
47impl<D: Device> Tensor<D, Bool> {
48 pub fn allclose(&self, other: &Self) -> crate::Result<bool> {
49 if self.element_count() != other.element_count() {
50 return Ok(false);
51 }
52 D::b_allclose(&*self.storage_read()?, self.layout(), &*other.storage_read()?, other.layout())
53 }
54}
55
56impl<D: Device> Tensor<D, Bool> {
59 pub fn false_count(&self) -> crate::Result<usize> {
60 Ok(self.element_count() - self.true_count()?)
61 }
62}
63
64fn fmt_f64(v: f64, precision: usize) -> String {
76 let abs = v.abs();
77 if abs == 0.0 || (abs >= 0.001 && abs < 1e5) {
78 format!("{:.prec$}", v, prec = precision)
79 } else {
80 format!("{:.prec$e}", v, prec = precision)
81 }
82}
83
84fn write_nd(buf: &mut String, data: &[String], dims: &[usize], depth: usize, indent: usize) {
85 if dims.is_empty() {
86 buf.push_str(&data[0]);
88 return;
89 }
90 if dims.len() == 1 {
91 buf.push('[');
92 for (i, v) in data.iter().enumerate() {
93 if i > 0 {
94 buf.push_str(", ");
95 }
96 buf.push_str(v);
97 }
98 buf.push(']');
99 return;
100 }
101 let stride: usize = dims[1..].iter().product();
103 buf.push('[');
104 for i in 0..dims[0] {
105 if i > 0 {
106 buf.push(',');
107 buf.push('\n');
108 for _ in 0..indent + depth + 1 {
109 buf.push(' ');
110 }
111 }
112 let slice = &data[i * stride..(i + 1) * stride];
113 write_nd(buf, slice, &dims[1..], depth + 1, indent);
114 }
115 buf.push(']');
116}
117
118impl<D: Device> std::fmt::Display for Tensor<D, Float> {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 const PREC: usize = 4;
121 let vals = match self.to_vec() {
122 Ok(v) => v,
123 Err(e) => return write!(f, "<Tensor error: {}>", e),
124 };
125 let strs: Vec<String> = vals.iter().map(|&v| fmt_f64(v, PREC)).collect();
126 let dtype_str = match self.dtype() {
127 FloatDType::F32 => "f32",
128 FloatDType::F64 => "f64",
129 };
130 let mut buf = format!("Tensor<{}>(", dtype_str);
131 let indent = buf.len();
132 write_nd(&mut buf, &strs, self.shape().dims(), 0, indent);
133 buf.push(')');
134 write!(f, "{}", buf)
135 }
136}
137
138impl<D: Device> std::fmt::Display for Tensor<D, Int> {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 let vals = match self.to_vec() {
141 Ok(v) => v,
142 Err(e) => return write!(f, "<Tensor error: {}>", e),
143 };
144 let strs: Vec<String> = vals.iter().map(|v| v.to_string()).collect();
145 let dtype_str = match self.dtype() {
146 IntDType::I32 => "i32",
147 IntDType::U32 => "u32",
148 IntDType::U8 => "u8",
149 };
150 let mut buf = format!("Tensor<{}>(", dtype_str);
151 let indent = buf.len();
152 write_nd(&mut buf, &strs, self.shape().dims(), 0, indent);
153 buf.push(')');
154 write!(f, "{}", buf)
155 }
156}
157
158impl<D: Device> std::fmt::Display for Tensor<D, Bool> {
159 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160 let vals = match self.to_vec() {
161 Ok(v) => v,
162 Err(e) => return write!(f, "<Tensor error: {}>", e),
163 };
164 let strs: Vec<String> = vals.iter().map(|v| v.to_string()).collect();
165 let mut buf = "Tensor<bool>(".to_string();
166 let indent = buf.len();
167 write_nd(&mut buf, &strs, self.shape().dims(), 0, indent);
168 buf.push(')');
169 write!(f, "{}", buf)
170 }
171}