gds/
utils.rs

1/// Contains some helper functions used in the gds crate.
2
3extern crate byteorder;
4
5use byteorder::{ByteOrder, BigEndian};
6
7/// Convert a slice of bytes into a 32 bit real.
8///
9/// The used format is not conform to IEEE floats as it uses 16 as base and
10/// excess 64 notation for the exponent. The first byte is used for the
11/// exponent (bits 2-8) and the sign (bit 1).
12pub fn bytes_to_gds_real32(bytes: &[u8]) -> f32 {
13    let exp: i8 = ((0b01111111 & bytes[0]) as i8) - 64 - 6;
14    let mut man_arr = [0;4];
15    man_arr[1..].copy_from_slice(&bytes[1..]);
16    let man_arr = man_arr;
17    let man: f32 = BigEndian::read_u32(&man_arr) as f32;
18    let base: f32 = 16.;
19    if (0b10000000 & bytes[0]) == 0{
20        man*base.powi(exp as i32)
21    } else {
22        -man*base.powi(exp as i32)
23    }
24}
25
26/// Convert a slice of bytes into a 64 bit real.
27///
28/// The used format is not conform to IEEE floats as it uses 16 as base and
29/// excess 64 notation for the exponent. The first byte is used for the
30/// exponent (bits 2-8) and the sign (bit 1).
31pub fn bytes_to_gds_real(bytes: &[u8]) -> f64 {
32    let exp: i8 = ((0b01111111 & bytes[0]) as i8) - 64 - 14;
33    let mut man_arr = [0;8];
34    man_arr[1..].copy_from_slice(&bytes[1..]);
35    let man: f64 = BigEndian::read_u64(&man_arr) as f64;
36    let base: f64 = 16.;
37    if (0b10000000 & bytes[0]) == 0{
38        man*base.powi(exp as i32)
39    } else {
40        -man*base.powi(exp as i32)
41    }
42}
43
44/// Converts a 64 bit real into a array of bytes.
45///
46/// The used format is not conform to IEEE floats as it uses 16 as base and
47/// excess 64 notation for the exponent. The first byte is used for the
48/// exponent (bits 2-8) and the sign (bit 1).
49pub fn gds_real_to_bytes(r: f64) -> [u8;8] {
50    let mut exp: u8 = 64;
51    let mut man: f64 = r.abs();
52    let base: f64 = 16.;
53    if man != 0. {
54        while man > 1. {
55            man /= 16.;
56            exp += 1;
57        }
58        while man < 1./16. {
59            man *= 16.;
60            exp -= 1;
61        }
62    }
63    let man: u64 = (man*base.powi(14)) as u64;
64    let mut man_arr = [0;8];
65    BigEndian::write_u64(&mut man_arr,man);
66    if r < 0. {
67        exp |= 0b10000000;
68    } else {
69        exp &= 0b01111111;
70    }
71    let mut out_arr = [0;8];
72    out_arr[0] = exp;
73    out_arr[1..].copy_from_slice(&man_arr[1..8]);
74    out_arr
75}
76
77/// Converts a 32 bit real into a array of bytes.
78///
79/// The used format is not conform to IEEE floats as it uses 16 as base and
80/// excess 64 notation for the exponent. The first byte is used for the
81/// exponent (bits 2-8) and the sign (bit 1).
82pub fn gds_real_32_to_bytes(r: f32) -> [u8;4] {
83    let mut exp: u8 = 64;
84    let mut man: f32 = r.abs();
85    let base: f32 = 16.;
86    if man != 0. {
87        while man > 1. {
88            man /= 16.;
89            exp += 1;
90        }
91        while man < 1./16. {
92            man *= 16.;
93            exp -= 1;
94        }
95    }
96    let man: u32 = (man*base.powi(6)) as u32;
97    let mut man_arr = [0;4];
98    BigEndian::write_u32(&mut man_arr,man);
99    if r < 0. {
100        exp |= 0b10000000;
101    } else {
102        exp &= 0b01111111;
103    }
104    let mut out_arr = [0;4];
105    out_arr[0] = exp;
106    out_arr[1..].copy_from_slice(&man_arr[1..4]);
107    out_arr
108}
109
110/// Converts a 16 bit signed integer into a vector of bytes.
111pub fn i16_to_vec(i: i16) -> Vec<u8> {
112    let mut buf: [u8;2] = [0;2];
113    BigEndian::write_i16(&mut buf,i);
114    buf.to_vec()
115}
116
117/// Converts a 16 bit unsigned integer into a vector of bytes.
118pub fn u16_to_vec(i: u16) -> Vec<u8> {
119    let mut buf: [u8;2] = [0;2];
120    BigEndian::write_u16(&mut buf,i);
121    buf.to_vec()
122}
123
124/// Converts a 32 bit signed integer into a vector of bytes.
125pub fn i32_to_vec(i: i32) -> Vec<u8> {
126    let mut buf: [u8;4] = [0;4];
127    BigEndian::write_i32(&mut buf,i);
128    buf.to_vec()
129}
130
131/// Converts a 32 bit unsigned integer into a vector of bytes.
132pub fn u32_to_vec(i: u32) -> Vec<u8> {
133    let mut buf: [u8;4] = [0;4];
134    BigEndian::write_u32(&mut buf,i);
135    buf.to_vec()
136}