add FloatTooBigError
This commit is contained in:
parent
babd7f1402
commit
e42ac03c95
39
src/basic.rs
39
src/basic.rs
@ -3,6 +3,7 @@
|
|||||||
///
|
///
|
||||||
use byteorder::{ByteOrder, BigEndian};
|
use byteorder::{ByteOrder, BigEndian};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
pub type OResult = Result<usize, io::Error>;
|
pub type OResult = Result<usize, io::Error>;
|
||||||
|
|
||||||
@ -14,7 +15,6 @@ pub enum ErrType {
|
|||||||
Failed(String),
|
Failed(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn fail<O>(input: &[u8], msg: String) -> IResult<O> {
|
pub fn fail<O>(input: &[u8], msg: String) -> IResult<O> {
|
||||||
Err((input, ErrType::Failed(msg)))
|
Err((input, ErrType::Failed(msg)))
|
||||||
}
|
}
|
||||||
@ -118,20 +118,21 @@ pub fn bitarray2int(bits: &[bool; 16]) -> u16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn pack_bitarray(buf: &mut [u8], bits: &[bool; 16]) {
|
pub fn pack_bitarray(buf: &mut [u8], bits: &[bool; 16]) {
|
||||||
BigEndian::write_u16(buf, bitarray2int(bits))
|
BigEndian::write_u16(buf, bitarray2int(bits));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn pack_int2(buf: &mut [u8], int: i16) {
|
pub fn pack_int2(buf: &mut [u8], int: i16) {
|
||||||
BigEndian::write_i16(buf, int)
|
BigEndian::write_i16(buf, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pack_int4(buf: &mut [u8], int: i32) {
|
pub fn pack_int4(buf: &mut [u8], int: i32) {
|
||||||
BigEndian::write_i32(buf, int)
|
BigEndian::write_i32(buf, int);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pack_real8(buf: &mut [u8], fnum: f64) {
|
pub fn pack_real8(buf: &mut [u8], fnum: f64) -> Result<(), FloatTooBigError> {
|
||||||
BigEndian::write_u64(buf, encode_real8(fnum))
|
BigEndian::write_u64(buf, encode_real8(fnum)?);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pack_ascii(buf: &mut [u8], data: &[u8]) -> usize {
|
pub fn pack_ascii(buf: &mut [u8], data: &[u8]) -> usize {
|
||||||
@ -156,8 +157,18 @@ pub fn pack_datetime(buf: &mut [u8], date: &[i16; 6]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FloatTooBigError {
|
||||||
|
float_value: f64,
|
||||||
|
}
|
||||||
|
impl fmt::Display for FloatTooBigError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Float {0} is too large for Real8", self.float_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert from float64 to GDS REAL8 representation.
|
/// Convert from float64 to GDS REAL8 representation.
|
||||||
pub fn encode_real8(fnum: f64) -> u64 {
|
pub fn encode_real8(fnum: f64) -> Result<u64, FloatTooBigError> {
|
||||||
// Split the ieee float bitfields
|
// Split the ieee float bitfields
|
||||||
let ieee = fnum.to_bits();
|
let ieee = fnum.to_bits();
|
||||||
let sign = ieee & 0x8000_0000_0000_0000;
|
let sign = ieee & 0x8000_0000_0000_0000;
|
||||||
@ -166,7 +177,7 @@ pub fn encode_real8(fnum: f64) -> u64 {
|
|||||||
|
|
||||||
let subnorm = (ieee_exp == 0) & (ieee_mant != 0);
|
let subnorm = (ieee_exp == 0) & (ieee_mant != 0);
|
||||||
if (ieee_exp == 0) & (ieee_mant == 0) {
|
if (ieee_exp == 0) & (ieee_mant == 0) {
|
||||||
return 0
|
return Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IEEE normal double is (1 + ieee_mant / 2^52) * 2^(ieee_exp - 1023)
|
// IEEE normal double is (1 + ieee_mant / 2^52) * 2^(ieee_exp - 1023)
|
||||||
@ -207,7 +218,7 @@ pub fn encode_real8(fnum: f64) -> u64 {
|
|||||||
|
|
||||||
if gds_exp < -14 {
|
if gds_exp < -14 {
|
||||||
// number is too small
|
// number is too small
|
||||||
return 0
|
return Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
let neg_biased = gds_exp < 0;
|
let neg_biased = gds_exp < 0;
|
||||||
@ -218,13 +229,13 @@ pub fn encode_real8(fnum: f64) -> u64 {
|
|||||||
|
|
||||||
let too_big = (gds_exp > 0x7f) & !subnorm;
|
let too_big = (gds_exp > 0x7f) & !subnorm;
|
||||||
if too_big {
|
if too_big {
|
||||||
panic!("Number too big for real8 format"); //TODO error handling
|
return Err(FloatTooBigError{float_value: fnum});
|
||||||
}
|
}
|
||||||
|
|
||||||
let gds_exp_bits = (gds_exp as u64) << 56;
|
let gds_exp_bits = (gds_exp as u64) << 56;
|
||||||
|
|
||||||
let real8 = sign | gds_exp_bits | gds_mant;
|
let real8 = sign | gds_exp_bits | gds_mant;
|
||||||
real8
|
Ok(real8)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -281,7 +292,7 @@ mod tests {
|
|||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_encode_real8_panic() {
|
fn test_encode_real8_panic() {
|
||||||
use crate::basic::encode_real8;
|
use crate::basic::encode_real8;
|
||||||
encode_real8(1e80);
|
encode_real8(1e80).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -348,7 +359,7 @@ mod tests {
|
|||||||
const REALS: [f64; 5] = [1.0, -2.0, 1e-9, 1e-3, 1e-12];
|
const REALS: [f64; 5] = [1.0, -2.0, 1e-9, 1e-3, 1e-12];
|
||||||
for vv in REALS {
|
for vv in REALS {
|
||||||
print!("{vv}\n");
|
print!("{vv}\n");
|
||||||
assert!((decode_real8(encode_real8(vv)) - vv).abs() < f64::EPSILON);
|
assert!((decode_real8(encode_real8(vv).unwrap()) - vv).abs() < f64::EPSILON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,7 +370,7 @@ mod tests {
|
|||||||
const REALS: [f64; COUNT] = [0.0, 1.0, -1.0, 0.5, 1e-9, 1e-3, 1e-12];
|
const REALS: [f64; COUNT] = [0.0, 1.0, -1.0, 0.5, 1e-9, 1e-3, 1e-12];
|
||||||
let mut buf = [10; 8 * COUNT];
|
let mut buf = [10; 8 * COUNT];
|
||||||
for (ii, &vv) in REALS.iter().enumerate() {
|
for (ii, &vv) in REALS.iter().enumerate() {
|
||||||
pack_real8(&mut buf[ii * 8..], vv);
|
pack_real8(&mut buf[ii * 8..], vv).unwrap();
|
||||||
}
|
}
|
||||||
for (ii, &vv) in REALS.iter().enumerate() {
|
for (ii, &vv) in REALS.iter().enumerate() {
|
||||||
print!("{vv}\n");
|
print!("{vv}\n");
|
||||||
|
@ -279,7 +279,7 @@ impl RecordData for Real8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pack_into(buf: &mut [u8], data: &Self::InData) {
|
fn pack_into(buf: &mut [u8], data: &Self::InData) {
|
||||||
pack_real8(buf, *data)
|
pack_real8(buf, *data).expect(&format!("Float {0} too big for Real8", data))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pack(data: &Self::InData) -> Self::ByteData {
|
fn pack(data: &Self::InData) -> Self::ByteData {
|
||||||
@ -303,8 +303,8 @@ impl RecordData for Real8Pair {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pack_into(buf: &mut [u8], data: &Self::InData) {
|
fn pack_into(buf: &mut [u8], data: &Self::InData) {
|
||||||
pack_real8(&mut buf[8 * 0..], data.0);
|
pack_real8(&mut buf[8 * 0..], data.0).expect(&format!("Float.0 {0} too big for Real8", data.0));
|
||||||
pack_real8(&mut buf[8 * 1..], data.1);
|
pack_real8(&mut buf[8 * 1..], data.1).expect(&format!("Float.1 {0} too big for Real8", data.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pack(data: &Self::InData) -> Self::ByteData {
|
fn pack(data: &Self::InData) -> Self::ByteData {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user