parallel_processor/
memory_data_size.rs1#[macro_export]
6macro_rules! implement_display {
7 ($($t:ty)*) => ($(
8
9 impl ::std::fmt::Display for $t {
10 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
11 let (unit, value) = self.get_appropriate_units();
12 value.fmt(f)?; write!(f, "\u{00A0}{}", unit)
14 }
15 }
16 )*)
17}
18
19macro_rules! implement_measurement {
22 ($($t:ty)*) => ($(
23
24 implement_display!( $t );
25
26 impl ::std::ops::Add for $t {
27 type Output = Self;
28
29 fn add(self, rhs: Self) -> Self {
30 Self::from_base_units(self.as_base_units() + rhs.as_base_units())
31 }
32 }
33
34 impl ::std::ops::Sub for $t {
35 type Output = Self;
36
37 fn sub(self, rhs: Self) -> Self {
38 Self::from_base_units(self.as_base_units() - rhs.as_base_units())
39 }
40 }
41
42 impl ::std::ops::Div<$t> for $t {
45 type Output = f64;
46
47 fn div(self, rhs: Self) -> f64 {
48 self.as_base_units() / rhs.as_base_units()
49 }
50 }
51
52 impl ::std::ops::Div<f64> for $t {
55 type Output = Self;
56
57 fn div(self, rhs: f64) -> Self {
58 Self::from_base_units(self.as_base_units() / rhs)
59 }
60 }
61
62 impl ::std::ops::Mul<f64> for $t {
65 type Output = Self;
66
67 fn mul(self, rhs: f64) -> Self {
68 Self::from_base_units(self.as_base_units() * rhs)
69 }
70 }
71
72 impl ::std::ops::Mul<$t> for f64 {
74 type Output = $t;
75
76 fn mul(self, rhs: $t) -> $t {
77 rhs * self
78 }
79 }
80
81 impl ::std::cmp::Eq for $t { }
82 impl ::std::cmp::PartialEq for $t {
83 fn eq(&self, other: &Self) -> bool {
84 self.as_base_units() == other.as_base_units()
85 }
86 }
87
88 impl ::std::cmp::PartialOrd for $t {
89 fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
90 self.as_base_units().partial_cmp(&other.as_base_units())
91 }
92 }
93 )*)
94}
95
96#[derive(Copy, Clone, Debug)]
104pub struct MemoryDataSize {
105 pub octets: f64,
107}
108
109impl MemoryDataSize {
110 pub const OCTET_BIT_FACTOR: f64 = 0.125;
112
113 pub const OCTET_KILOOCTET_FACTOR: u64 = 1000;
115 pub const OCTET_MEGAOCTET_FACTOR: u64 = 1000 * 1000;
116 pub const OCTET_GIGAOCTET_FACTOR: u64 = 1000 * 1000 * 1000;
117 pub const OCTET_TERAOCTET_FACTOR: u64 = 1000 * 1000 * 1000 * 1000;
118
119 pub const OCTET_KIBIOCTET_FACTOR: u64 = 1024;
121 pub const OCTET_MEBIOCTET_FACTOR: u64 = 1024 * 1024;
122 pub const OCTET_GIBIOCTET_FACTOR: u64 = 1024 * 1024 * 1024;
123 pub const OCTET_TEBIOCTET_FACTOR: u64 = 1024 * 1024 * 1024 * 1024;
124
125 pub const fn from_octets(octets: f64) -> Self {
127 MemoryDataSize { octets }
128 }
129
130 pub fn from_bits(bits: f64) -> Self {
132 Self::from_octets(bits * Self::OCTET_BIT_FACTOR)
133 }
134
135 pub const fn from_kilooctets(kilooctets: u64) -> Self {
138 Self::from_octets((kilooctets * Self::OCTET_KILOOCTET_FACTOR) as f64)
139 }
140
141 pub const fn from_megaoctets(megaoctets: u64) -> Self {
143 Self::from_octets((megaoctets * Self::OCTET_MEGAOCTET_FACTOR) as f64)
144 }
145
146 pub const fn from_gigaoctets(gigaoctets: u64) -> Self {
148 Self::from_octets((gigaoctets * Self::OCTET_GIGAOCTET_FACTOR) as f64)
149 }
150
151 pub const fn from_teraoctets(teraoctets: u64) -> Self {
153 Self::from_octets((teraoctets * Self::OCTET_TERAOCTET_FACTOR) as f64)
154 }
155
156 pub const fn from_kibioctets(kibioctets: u64) -> Self {
158 Self::from_octets((kibioctets * Self::OCTET_KIBIOCTET_FACTOR) as f64)
159 }
160
161 pub const fn from_mebioctets(mebioctets: u64) -> Self {
163 Self::from_octets((mebioctets * Self::OCTET_MEBIOCTET_FACTOR) as f64)
164 }
165
166 pub const fn from_gibioctets(gibioctets: u64) -> Self {
168 Self::from_octets((gibioctets * Self::OCTET_GIBIOCTET_FACTOR) as f64)
169 }
170
171 pub const fn from_tebioctets(tebioctets: u64) -> Self {
173 Self::from_octets((tebioctets * Self::OCTET_TEBIOCTET_FACTOR) as f64)
174 }
175
176 pub fn as_octets(&self) -> f64 {
178 self.octets
179 }
180
181 pub fn as_bits(&self) -> f64 {
183 self.octets / Self::OCTET_BIT_FACTOR
184 }
185
186 pub fn as_kilooctets(&self) -> f64 {
188 self.octets / (Self::OCTET_KILOOCTET_FACTOR as f64)
189 }
190
191 pub fn as_megaoctets(&self) -> f64 {
193 self.octets / (Self::OCTET_MEGAOCTET_FACTOR as f64)
194 }
195
196 pub fn as_gigaoctets(&self) -> f64 {
198 self.octets / (Self::OCTET_GIGAOCTET_FACTOR as f64)
199 }
200
201 pub fn as_teraoctets(&self) -> f64 {
203 self.octets / (Self::OCTET_TERAOCTET_FACTOR as f64)
204 }
205
206 pub fn as_kibioctets(&self) -> f64 {
208 self.octets / (Self::OCTET_KIBIOCTET_FACTOR as f64)
209 }
210
211 pub fn as_mebioctets(&self) -> f64 {
213 self.octets / (Self::OCTET_MEBIOCTET_FACTOR as f64)
214 }
215
216 pub fn as_gibioctets(&self) -> f64 {
218 self.octets / (Self::OCTET_GIBIOCTET_FACTOR as f64)
219 }
220
221 pub fn as_tebioctets(&self) -> f64 {
223 self.octets / (Self::OCTET_TEBIOCTET_FACTOR as f64)
224 }
225
226 fn as_base_units(&self) -> f64 {
227 self.octets
228 }
229
230 fn from_base_units(units: f64) -> Self {
231 Self::from_octets(units)
232 }
233
234 fn get_appropriate_units(&self) -> (&'static str, f64) {
235 let list = [
237 ("octets", 1.0),
238 ("KiB", 1024.0),
239 ("MiB", 1024.0 * 1024.0),
240 ("GiB", 1024.0 * 1024.0 * 1024.0),
241 ("TiB", 1024.0 * 1024.0 * 1024.0 * 1024.0),
242 ("PiB", 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0),
243 ("EiB", 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0),
244 ];
245 self.pick_appropriate_units(&list)
246 }
247
248 fn pick_appropriate_units(&self, list: &[(&'static str, f64)]) -> (&'static str, f64) {
254 for &(unit, ref scale) in list.iter().rev() {
255 let value = self.as_base_units() / scale;
256 if value >= 1.0 || value <= -1.0 {
257 return (unit, value);
258 }
259 }
260 (list[0].0, self.as_base_units() / list[0].1)
261 }
262
263 pub fn as_bytes(&self) -> usize {
264 self.as_base_units() as usize
265 }
266 pub fn from_bytes(bytes: usize) -> Self {
267 Self::from_base_units(bytes as f64)
268 }
269 pub fn max(self, other: Self) -> Self {
270 Self::from_base_units(self.as_base_units().max(other.as_base_units()))
271 }
272}
273
274implement_measurement! { MemoryDataSize }
275
276#[cfg(test)]
277mod test {
278 use crate::memory_data_size::MemoryDataSize;
279
280 const DEFAULT_DELTA: f64 = 1e-5;
281
282 fn almost_eq_delta(a: f64, b: f64, d: f64) -> bool {
284 ((a - b).abs() / a) < d
285 }
286
287 fn assert_almost_eq_delta(a: f64, b: f64, d: f64) {
289 if !almost_eq_delta(a, b, d) {
290 panic!("assertion failed: {:?} != {:?} (within {:?})", a, b, d);
291 }
292 }
293
294 fn assert_almost_eq(a: f64, b: f64) {
296 assert_almost_eq_delta(a, b, DEFAULT_DELTA);
297 }
298
299 #[test]
301 fn bits() {
302 let i1 = MemoryDataSize::from_octets(100.0);
303 let r1 = i1.as_bits();
304
305 let i2 = MemoryDataSize::from_bits(100.0);
306 let r2 = i2.as_octets();
307
308 assert_almost_eq(r1, 800.0);
309 assert_almost_eq(r2, 12.5);
310 }
311
312 #[test]
313 fn kilooctet() {
314 let i1 = MemoryDataSize::from_octets(100.0);
315 let r1 = i1.as_kilooctets();
316
317 let i2 = MemoryDataSize::from_kilooctets(100);
318 let r2 = i2.as_octets();
319
320 assert_almost_eq(r1, 0.1);
321 assert_almost_eq(r2, 1e5);
322 }
323
324 #[test]
325 fn megaoctet() {
326 let i1 = MemoryDataSize::from_octets(100.0);
327 let r1 = i1.as_megaoctets();
328
329 let i2 = MemoryDataSize::from_megaoctets(100);
330 let r2 = i2.as_octets();
331
332 assert_almost_eq(r1, 0.0001);
333 assert_almost_eq(r2, 1e8);
334 }
335
336 #[test]
337 fn gigaoctet() {
338 let i1 = MemoryDataSize::from_octets(100.0);
339 let r1 = i1.as_gigaoctets();
340
341 let i2 = MemoryDataSize::from_gigaoctets(100);
342 let r2 = i2.as_octets();
343
344 assert_almost_eq(r1, 1e-7);
345 assert_almost_eq(r2, 1e11);
346 }
347
348 #[test]
349 fn teraoctet() {
350 let i1 = MemoryDataSize::from_octets(100.0);
351 let r1 = i1.as_teraoctets();
352
353 let i2 = MemoryDataSize::from_teraoctets(100);
354 let r2 = i2.as_octets();
355
356 assert_almost_eq(r1, 1e-10);
357 assert_almost_eq(r2, 1e14);
358 }
359
360 #[test]
362 fn kibioctet() {
363 let i1 = MemoryDataSize::from_octets(100.0);
364 let r1 = i1.as_kibioctets();
365
366 let i2 = MemoryDataSize::from_kibioctets(100);
367 let r2 = i2.as_octets();
368
369 assert_almost_eq(r1, 0.09765625);
370 assert_almost_eq(r2, 102400.0);
371 }
372
373 #[test]
374 fn mebioctet() {
375 let i1 = MemoryDataSize::from_octets(100.0);
376 let r1 = i1.as_mebioctets();
377
378 let i2 = MemoryDataSize::from_mebioctets(100);
379 let r2 = i2.as_octets();
380
381 assert_almost_eq(r1, 9.536743e-5);
382 assert_almost_eq(r2, 104857600.0);
383 }
384
385 #[test]
386 fn gibioctets() {
387 let i1 = MemoryDataSize::from_octets(100.0);
388 let r1 = i1.as_gibioctets();
389
390 let i2 = MemoryDataSize::from_gibioctets(100);
391 let r2 = i2.as_octets();
392
393 assert_almost_eq(r1, 9.313226e-8);
394 assert_almost_eq(r2, 107374182400.0);
395 }
396
397 #[test]
398 fn tebioctets() {
399 let i1 = MemoryDataSize::from_octets(100.0);
400 let r1 = i1.as_tebioctets();
401
402 let i2 = MemoryDataSize::from_tebioctets(100);
403 let r2 = i2.as_octets();
404
405 assert_almost_eq(r1, 9.094947e-11);
406 assert_almost_eq(r2, 109951162777600.0);
407 }
408
409 #[test]
411 fn add() {
412 let a = MemoryDataSize::from_octets(2.0);
413 let b = MemoryDataSize::from_octets(4.0);
414 let c = a + b;
415 assert_almost_eq(c.as_octets(), 6.0);
416 }
417
418 #[test]
419 fn sub() {
420 let a = MemoryDataSize::from_octets(2.0);
421 let b = MemoryDataSize::from_octets(4.0);
422 let c = a - b;
423 assert_almost_eq(c.as_octets(), -2.0);
424 }
425
426 #[test]
427 fn mul() {
428 let b = MemoryDataSize::from_octets(4.0);
429 let d = b * 2.0;
430 assert_almost_eq(d.as_octets(), 8.0);
431 }
432
433 #[test]
434 fn div() {
435 let b = MemoryDataSize::from_octets(4.0);
436 let d = b / 2.0;
437 assert_almost_eq(d.as_octets(), 2.0);
438 }
439
440 #[test]
441 fn eq() {
442 let a = MemoryDataSize::from_octets(2.0);
443 let b = MemoryDataSize::from_octets(2.0);
444 assert_eq!(a == b, true);
445 }
446
447 #[test]
448 fn neq() {
449 let a = MemoryDataSize::from_octets(2.0);
450 let b = MemoryDataSize::from_octets(4.0);
451 assert_eq!(a == b, false);
452 }
453
454 #[test]
455 fn cmp() {
456 let a = MemoryDataSize::from_octets(2.0);
457 let b = MemoryDataSize::from_octets(4.0);
458 assert_eq!(a < b, true);
459 assert_eq!(a <= b, true);
460 assert_eq!(a > b, false);
461 assert_eq!(a >= b, false);
462 }
463}