Skip to content
This repository has been archived by the owner on Aug 15, 2021. It is now read-only.

Commit

Permalink
Add half (f16) encoding
Browse files Browse the repository at this point in the history
Add a dependency on the excellent half crate.
  • Loading branch information
pyfisch committed Jul 22, 2018
1 parent e99d3e0 commit 77f1a8a
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ categories = ["encoding"]

[dependencies]
byteorder = "1.0.0"
half = "1.1.2"
serde = "1.0.14"

[dev-dependencies]
Expand Down
21 changes: 2 additions & 19 deletions src/de.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Deserialization.

use byteorder::{ByteOrder, BigEndian};
use half::f16;
use serde::de;
use std::io;
use std::str;
Expand Down Expand Up @@ -366,25 +367,7 @@ where
}

fn parse_f16(&mut self) -> Result<f32> {
let half = self.parse_u16()?;
let exp = (half >> 10) & 0x1f;
let mant = half & 0x3ff;

let mut val = if exp == 0 {
(mant as f32) * (-24f32).exp2()
} else if exp != 31 {
((mant + 1024) as f32) * (exp as f32 - 25.).exp2()
} else if mant == 0 {
f32::INFINITY
} else {
f32::NAN
};

if half & 0x8000 != 0 {
val = -val;
}

Ok(val)
Ok(f32::from(f16::from_bits(self.parse_u16()?)))
}

fn parse_f32(&mut self) -> Result<f32> {
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
#![deny(missing_docs)]

extern crate byteorder;
extern crate half;

#[macro_use]
extern crate serde;
Expand Down
6 changes: 5 additions & 1 deletion src/ser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Serialize a Rust data structure to CBOR data.
use byteorder::{ByteOrder, BigEndian};
use half::f16;
use serde::ser::{self, Serialize};
use std::io;

Expand Down Expand Up @@ -298,8 +299,11 @@ where
}
} else if value.is_nan() {
self.writer.write_all(&[0xf9, 0x7e, 0x00])
} else if f32::from(f16::from_f32(value)) == value {
let mut buf = [0xf9, 0, 0];
BigEndian::write_u16(&mut buf[1..], f16::from_f32(value).as_bits());
self.writer.write_all(&buf)
} else {
// TODO encode as f16 when possible
let mut buf = [0xfa, 0, 0, 0, 0];
BigEndian::write_f32(&mut buf[1..], value);
self.writer.write_all(&buf)
Expand Down
7 changes: 7 additions & 0 deletions tests/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,10 @@ fn test_byte_string() {
// byte strings > 2^32 bytes have 9-byte headers, but they take too much RAM
// to test in Travis.
}

#[test]
fn test_half() {
let vec = to_vec(&42.5f32).unwrap();
assert_eq!(vec, b"\xF9\x51\x50");
assert_eq!(from_slice::<f32>(&vec[..]).unwrap(), 42.5f32);
}

0 comments on commit 77f1a8a

Please sign in to comment.