Skip to content

Commit 76306b2

Browse files
committed
Add half-float support for struct
1 parent 108e1ef commit 76306b2

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_struct.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -723,8 +723,6 @@ def test_module_func(self):
723723
self.assertRaises(StopIteration, next, it)
724724
self.assertRaises(StopIteration, next, it)
725725

726-
# TODO: RUSTPYTHON
727-
@unittest.expectedFailure
728726
def test_half_float(self):
729727
# Little-endian examples from:
730728
# http://en.wikipedia.org/wiki/Half_precision_floating-point_format

vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ timsort = "0.1"
7878
thiserror = "1.0"
7979
atty = "0.2"
8080
static_assertions = "1.1"
81+
half = "1.6"
8182

8283
## unicode stuff
8384
unicode_names2 = "0.4"

vm/src/stdlib/pystruct.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub(crate) mod _struct {
3535
};
3636
use crate::slots::PyIter;
3737
use crate::VirtualMachine;
38+
use half::f16;
3839

3940
#[derive(Debug, Copy, Clone, PartialEq)]
4041
enum Endianness {
@@ -72,7 +73,7 @@ pub(crate) mod _struct {
7273
LongLong = b'q',
7374
ULongLong = b'Q',
7475
Bool = b'?',
75-
// TODO: Half = 'e',
76+
Half = b'e',
7677
Float = b'f',
7778
Double = b'd',
7879
VoidP = b'P',
@@ -149,6 +150,7 @@ pub(crate) mod _struct {
149150
LongLong => nonnative_info!(i64, $end),
150151
ULongLong => nonnative_info!(u64, $end),
151152
Bool => nonnative_info!(bool, $end),
153+
Half => nonnative_info!(f16, $end),
152154
Float => nonnative_info!(f32, $end),
153155
Double => nonnative_info!(f64, $end),
154156
_ => unreachable!(), // size_t or void*
@@ -182,6 +184,7 @@ pub(crate) mod _struct {
182184
LongLong => native_info!(raw::c_longlong),
183185
ULongLong => native_info!(raw::c_ulonglong),
184186
Bool => native_info!(bool),
187+
Half => native_info!(f16),
185188
Float => native_info!(raw::c_float),
186189
Double => native_info!(raw::c_double),
187190
VoidP => native_info!(*mut raw::c_void),
@@ -623,6 +626,29 @@ pub(crate) mod _struct {
623626
make_pack_float!(f32);
624627
make_pack_float!(f64);
625628

629+
impl Packable for f16 {
630+
fn pack<E: ByteOrder>(
631+
vm: &VirtualMachine,
632+
arg: PyObjectRef,
633+
data: &mut [u8],
634+
) -> PyResult<()> {
635+
let f_64 = float::try_float(&arg, vm)?;
636+
let f_16 = f16::from_f64(f_64);
637+
if f_16.is_infinite() != f_64.is_infinite() {
638+
return Err(
639+
vm.new_overflow_error("float too large to pack with e format".to_owned())
640+
);
641+
}
642+
f_16.to_bits().pack_int::<E>(data);
643+
Ok(())
644+
}
645+
646+
fn unpack<E: ByteOrder>(vm: &VirtualMachine, rdr: &[u8]) -> PyObjectRef {
647+
let i = PackInt::unpack_int::<E>(rdr);
648+
f16::from_bits(i).to_f64().into_pyobject(vm)
649+
}
650+
}
651+
626652
impl Packable for *mut raw::c_void {
627653
fn pack<E: ByteOrder>(
628654
vm: &VirtualMachine,

0 commit comments

Comments
 (0)