starkat99 / half-rs Goto Github PK
View Code? Open in Web Editor NEWHalf-precision floating point types f16 and bf16 for Rust.
Home Page: https://docs.rs/half/
License: Other
Half-precision floating point types f16 and bf16 for Rust.
Home Page: https://docs.rs/half/
License: Other
See if there's a Github action runner host that can do AArch64 images, would speed up CI immensely by avoiding running on QEMU. Compile times are just atrocious, even for small crate like this. Or find some other solution for testing AArch64.
I am interested in multiplying/adding/taking powers of f16
s. Does it make sense for these traits to be implemented in half
itself? Or is this something that I should be implementing on my end (e.g. by creating a newtype?),
I am currently implementing a popular file format in Rust which stores binary f16 arrays. As byteorder
does not support f16, I need to read these f16 arrays as u16 arrays and then convert them to f16, in order to correctly handle endianness.
I wondered if there could be some functionality in this library, which prevents users to just do array.iter().map(|u| f16::from_bits(u)).collect::<Vec<f16>>()
. This code iterates the whole array and allocates a new vector, but (I assume that) in memory, not a single bit is changed. All it probably does is basically copying the contents of the array element by element. But all it needs to do is really just interpreting the bits in a different way by representing it with a different type at compile time.
Is it maybe possible to reinterpret an array of u16 as an array of f16 by simply unsafely casting the raw pointers?
If not, certainly it's possible to provide an F16Slice <'a> (&'a [u16])
which maybe even implements ::std::ops::Index
with f16::from_bits(self.0[index])
, or something similar.
On the other hand, I can imagine that my use case is rather rare and not many people need to convert between large arrays of u16 and f16. Anyways, what do you think of that?
Also, Please correct me if I have overlooked something.
Is there a reason why to_f32() is private?
Debug is used more than Display since it can be derived, and is also used for containers. The interior u16 is an implementation detail, and almost certainly the user wants to see the numerical value not the bit value when using Debug, for example when working with vecs or arrays. Assertions, errors, all work with Debug, and this makes those unreadable.
Add support for the new AVX-512-FP16 x86 extension, which appears to already be available as unstable in . It allows for a wide variety of operations. Will need to be added to core::arch
core::arch
. Hardware using it isn't quite out yet though.
Extension specs: https://software.intel.com/content/dam/develop/external/us/en/documents-tps/intel-avx512-fp16.pdf
F16C hardware intrinsics still not stabilized, just needs stabilization PR rust-lang/stdarch#1234
Probably the biggest priority for crate now that const
conversions are done.
Would it be possible to introduce lossless TryFrom
implementations for bf16
and f16
types from Rust primitive f32
and f64
types so that for example f16::try_from(value).map(f16::to_f32)
is either Err
or Ok(value2)
with value == value2
for all possible value
s?
This means that if TryFrom
is Ok
the conversion was lossless and it is possible to fully recover the f32
or f64
value later on if no mutations happen in between. If TryFrom
yields Err
then it is not possible to losslessly convert the particular f32
or f64
value. No rounding shall take place.
I actually need this if this can be implemented efficiently. :)
We would like to use f16
in dfdx, a deep learning library. It would be very convenient if this crate implemented rand_distr::SampleUniform
for f16
.
Relevant issue in dfdx: coreylowman/dfdx#423
The trait would allow us to sample a random f16
from a uniform distribution. This seems like a generally useful feature, perhaps behind a feature gate. Other alternatives exist from our side, but they make the implementation more annoying.
I would be willing to implement this feature if a maintainer agrees that it is a good idea. Closing this issue is also a completely valid response if you believe that this trait implementation does not belong in this crate.
How do you cast a f32 variable into a f16 variable?
use half::f16;
use num::traits::FromPrimitive;
use half::*;
use half;
let a: f16 = (0.2f32).into();
println!("a {}",a);
| let a: f16 = (0.2f32).into();
| ^^^^^^^^ ---- required by a bound introduced by this call
| |
| the trait From<f32>
is not implemented for f16
|
= help: the following other types implement trait From<T>
:
<f16 as From>
<f16 as From>
= note: required for f32
to implement Into<f16>
So, I started a new embedded project with Rust, and I get this error when using half
(although indirectly, through canadensis_data_types
). Is it a bug on half
's end or my oversight?
When I tried to run an old project, I received a deprecation message.
warning: use of deprecated item 'half::vec::from_bits': use [`HalfBitsVecExt::reinterpret_into`](trait.HalfBitsVecExt.html#tymethod.reinterpret_into) instead
--> src\file\io.rs:344:12
|
344 | Ok(::half::vec::from_bits(data))
|
Looks like markdown source code. Could it be possible that the deprecation note does not support markdown?
Hi there,
It seems that the arrow
crate depends on half
.
├── arrow v42.0.0
│ ├── ahash v0.8.3
│ │ ├── cfg-if v1.0.0
│ │ ├── getrandom v0.2.10
│ │ │ ├── cfg-if v1.0.0
│ │ │ └── libc v0.2.146
│ │ └── once_cell v1.18.0
│ │ [build-dependencies]
│ │ └── version_check v0.9.4
│ ├── arrow-arith v42.0.0
│ │ ├── arrow-array v42.0.0
│ │ │ ├── ahash v0.8.3 (*)
│ │ │ ├── arrow-buffer v42.0.0
│ │ │ │ ├── half v2.2.1
(...)
With the version 2.3.0, the CI on my project seems to break: https://github.com/nyx-space/nyx/actions/runs/5370402979/jobs/9742460842 .
Compiling half v2.3.0
error[E0425]: cannot find function `_mm_cvtps_ph` in this scope
--> /root/.cargo/registry/src/index.crates.io-1cd66030c949c28d/half-2.3.0/src/binary16/arch/x86.rs:32:18
|
32 | let retval = _mm_cvtps_ph(vec.assume_init(), _MM_FROUND_TO_NEAREST_INT);
| ^^^^^^^^^^^^
--> /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/../../stdarch/crates/core_arch/src/x86/f16c.rs:33:1
|
= note: similarly named function `_mm_cvtph_ps` defined here
|
help: a function with a similar name exists
|
32 | let retval = _mm_cvtph_ps(vec.assume_init(), _MM_FROUND_TO_NEAREST_INT);
| ~~~~~~~~~~~~
help: consider importing this function
|
1 + use core::arch::x86::_mm_cvtps_ph;
|
error[E0425]: cannot find function `_mm_cvtps_ph` in this scope
--> /root/.cargo/registry/src/index.crates.io-1cd66030c949c28d/half-2.3.0/src/binary16/arch/x86.rs:50:18
|
50 | let retval = _mm_cvtps_ph(vec.assume_init(), _MM_FROUND_TO_NEAREST_INT);
| ^^^^^^^^^^^^
--> /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/../../stdarch/crates/core_arch/src/x86/f16c.rs:33:1
|
= note: similarly named function `_mm_cvtph_ps` defined here
|
help: a function with a similar name exists
|
50 | let retval = _mm_cvtph_ps(vec.assume_init(), _MM_FROUND_TO_NEAREST_INT);
| ~~~~~~~~~~~~
help: consider importing this function
|
1 + use core::arch::x86::_mm_cvtps_ph;
|
For more information about this error, try `rustc --explain E0425`.
Any idea if there is something I can do to fix this or do I need to wait until arrow fixes something on their end ? Or do you think this could be Github CI being slow at updating all of its dependencies ? (I suspect the latter is possible since another workflow seems to build).
Thanks
Two points of data from the Changelog:
Breaking Change Minimum supported Rust version is now 1.70.
and
Breaking Change Minimum supported Rust version policy reverted to original policy of allowing minimum supported Rust version updates for minor releases instead of only major to avoid segmentation and allow optimizing hardware implementations without unnecessary major releases.
Look, I can understand that this crate is probably depended upon by projects that have some anxiety about actually following semver to the letter, even if cargo is going to complain as-such if you don't. However, this change presents the following problem:
^MAJOR.MINOR.PATCH
instead of =MAJOR.MINOR.PATCH
(assuming one just writes e.g. 2.2.0
that actually means ^2.2.0
instead of =2.2.0
.image
crate for example uses exr
with the following dependency on 0.24.6: https://github.com/image-rs/image/blob/v0.24.6/Cargo.toml#L47C10-L47C10. The latest version of exr
(untagged) uses ^2.1.0
https://github.com/johannesvollmer/exrs/blob/master/Cargo.toml#L31.exr
and image
crate which used to work now don't. You've broken your stated policy without a new major release, so if you're one of these crate maintainers, you have no way of knowing that a minor version bump is now imposing a rusc1.70.0 dependency across the board for both previously released versions and currently released versions.The first point above (requiring 1.70.0) isn't necessarily a problem. It's not even a problem for your project to make a requirement that a minor version bump may impose a new minimum version requirement. What is a problem is that you changed that policy (where previously maintainers would expect to see a major version bump if there's a new min-req) with a minor version bump, which negates the whole point of the thing.
My organization is wasting time on this at a higher level by using the image
crate. This isn't their fault, and it is something we can work around because we're able to relatively easily upgrade to a newer rustc
. But it's completely unexpected and you're breaking every downstream crate by not making that policy explicit to crate maintainers who can opt into it (e.g. the maintainer of the exr
crate, @johannesvollmer).
Can you please yank 2.3.0 and 2.3.1 and please focus on a 3.0 release with this breaking change for the future? This is only going to cause more chaos as people start to update and time goes on...
I'm using rkyv for a project and it's quite helpful. I'd like to add optional support for it here as I'd like to have the space savings of half in my archived types. With the use of zerocopy
it should be quite straight forward.
There are many situations when an approximate comparison is useful for floats. The approx
crate appears to the the de-facto standard crate supporting standard approximate comparisons, so implementing the traits for f16
as an optional feature could be a useful addition.
Allow selecting how to round when converting down to f16
. Note that while x86 F16C hardware allows selecting rounding mode, ARM in particular does not, so keeping consistent across implementation may be an issue (current defaults on supported hardware/software are consistent for the moment, though adding ARM and other hardware later may not be consistent). Will be a bit tricky to get the interface right.
Use the 8x x86 SIMD conversions when appropriate, not just the 4x. These are _mm256_cvtph_ps and _mm256_cvtps_ph. Needs some profiling to determine which to use over the other and in what circumstances, possible that it might be better to use 8x always.
Current implementation uses mem::transmute
which is not ideal. Awaiting stabilization of rust-lang/rust#57241 which is blocked by general Rust float soundess discussions.
Hello,
I noticed that the sign of f32
NaNs are preserved when they are converted to f64
as indicated by this experiment: https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=b23459b96256c673aa6d84ed79a10f50.
But it appears f16
NaNs do not have this behavior. For example, the second assertion fails.
extern crate half;
use half::*;
fn main() {
let x = f16::from_bits(64513);
let y = x.to_f32();
assert!(x.is_sign_negative());
println!("{}", y);
assert!(y.is_sign_negative());
}
I couldn't find any useful information about whether the standard specifies this. So I'm not sure if f16
should be consistent with f32
with respect to this behavior.
Hello,
I found that some f32
values are converted differently depending on whether use-intrinsics
is enabled or not. I am using the 1.3.0 release version.
For example:
use half::f16;
let f = 2.9802322e-8f32;
let f2 = f16::from_f32(f);
println!("{}", f2);
prints 0
when intrinsics are enabled and 0.000000059604645
when intrinsics are not enabled.
I also found an example that is potentially a rounding direction mismatch:
use half::f16;
let f = 520.25f32;
let f2 = f16::from_f32(f);
println!("{}", f2);
prints 520
when intrinsics are enabled and 520.5
when not enabled.
Add vector arithmetic operations on slices/arrays of f16
, that can utilize SIMD hardware when available, like is already done for conversions.
Hey @starkat99, would you consider cutting a release for the current main branch ? Thank you!
In sonos/tract#916 I've been investigating fp16 math support with ARM hardware that supports it, and while it's not ready for a PR yet, I think that what I've found so far is promising.
By having a C file with simple functions like:
void add_f16(_Float16 *c, const _Float16 *a, const _Float16 *b) { *c = *a + *b; }
for add/sub/mul/div, and using them when a target arch or target feature is available (fp16 or fp16fhm?) would allow for significantly better performance in applications relying on the half crate (no need to convert constantly from f32 to f16).
When combined with LTO, it's possible to create applications and static libraries that properly embed and optimize these core operators, allowing for significant performance improvement on platforms that have hardware support!
The main problem is that not every toolchain supports _Float16, and so I'm worried that a combination of 'target supports fp16' + 'compiler does not support _Float16' will be true...
This would also add a dependency on the cc crate.
Since the primitive floats have the method to_bits
that does exactly what as_bits
does, it would be good to have an f16::to_bits
method, and maybe deprecate f16::as_bits
.
To be clear: While I think the purported value in allowing breaking changes vis-a-vis changing the MSRV in a minor version is debatable, this issue isn't about the policy itself, but rather how it was introduced.
Prior to 2.3.0, there was no indication that this crate would not adhere to SemVer, which in the Rust ecosystem is therefore tantamount to implicitly doing so. Therefore downstream crates with their own MSRVs can - and in at least 1 instance have - reasonably assumed they could depend on any 2.x version of half
. This is in fact the default behavior in Cargo if the version is specified as either 2.2
or 2.2.0
, for instance, as the resolver allows the rightmost non-zero version to change with new releases.
The fixed
crate is one example, with an explicit MSRV of 1.67, fully compatible with this crate's own MSRV of 1.58 up until 2.3. My own crate fast_poisson
, which also has an MSRV of 1.67, unexpectedly broke in CI this week, as it (indirectly) depends on fixed
which in turn depends on half
at version >= 1.8, < 3.0
- fixed
quite reasonably assumed this crate, saying nothing to the contrary, would follow SemVer.
I'm sure crates other than these two have had their MSRVs broken by half
suddenly introducing this policy of breaking changes in minor versions. Whether or not the policy itself is good, introducing it in a minor version is not, as the policy itself is a breaking change in its own right. I believe that the 2.3.x versions should be yanked and republished as 3.0, and the policy made explicit in the README (currently it exists nowhere I can see but in the 2.3.0 release notes) so that future users can be forewarned that this crate may not adhere to SemVer in future minor versions. Alternatively, a new 2.4.0 version that reverts the changes necessitating the MSRV bump could supersede the 2.3.x, with a 3.0 version re-introducing those changes and bump and explicitly publishing the policy.
On rust version 1.26 I get the following error. When I updated to Rust 1.27 the error went away.
error[E0599]: no function or associated item named from_bits
found for type f64
in the current scope
--> /Users/joshuabatty/.cargo/registry/src/github.com-1ecc6299db9ec823/half-1.1.1/src/lib.rs:808:9
|
808 | f64::from_bits(sign | exp | man)
| ^^^^^^^^^^^^^^ function or associated item not found in f64
|
= help: items from traits can only be used if the trait is in scope
= note: the following trait is implemented but not in scope, perhaps add a use
for it:
candidate #1: use core::num::Float;
Expose an [f16; 4]
(and [f16; 8]
, see #66) API in addition to the slice convenience traits.
Hi. I'm trying to serialize f16, but I'm stuck on it.
I'm using serde
feature, but when I use f16_var.serialize(serializer)
I'm getting unexpected results.
Example:
Value: 1.0
Serialization result: "15360"`
If I convert the value to f32 and serialize it, everything is fine, I will get "1.0"` as expected.
Running on Ubuntu 20 under WSL
Similarly to how num-traits and bytemuck are integrated, it would be cool to see the integration with the simba crate. It would allow f16 and bf16 to be used in the entire nalgebra ecosystem of crates.
It would be useful to derive Serialize and Deserialize for f16 to support serialization with serde.
Hello,
im working on an issue in the Android/Termux CI from uutils project.
The issue: It's currently only reproducable in our CI.
On my private PC I can't reproduce the issue.
After adding more logs and several CI test-runs, I managed to trace it down to the half-rs
crate:
#[test]
fn test_f16c_f16_to_f32_direct() {
let bo = ::od::byteorder_io::ByteOrder::Little;
let bits = bo.read_u16(&[0x00, 0x3c]);
let result_f16 = half::f16::from_bits(bits);
let result = f64::from(result_f16); // crashes here
assert_eq!(1.0, result);
}
The function in half-rs
responsible for converting f16 to f64 is this:
#[inline]
pub(crate) fn f16_to_f64(i: u16) -> f64 {
convert_fn! {
if x86_feature("f16c") {
unsafe { x86::f16_to_f32_x86_f16c(i) as f64 } // crashes here
} else if aarch64_feature("fp16") {
unsafe { aarch64::f16_to_f64_fp16(i) }
} else {
f16_to_f64_fallback(i)
}
}
}
I tried to trace it down even further, by extracting relevant code into a own test.
This test fails with SIG 4
. Which is "illegal instruction".
#[test]
fn test_f16c_direct() {
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::{_mm_cvtph_ps, __m128i, __m128};
#[cfg(target_arch = "x86")]
use std::arch::x86::{_mm_cvtph_ps, __m128i, __m128};
let i = 0u16;
let result: f32 = unsafe {
let mut vec = std::mem::MaybeUninit::<__m128i>::zeroed();
vec.as_mut_ptr().cast::<u16>().write(i);
let retval = _mm_cvtph_ps(vec.assume_init());
*(&retval as *const __m128).cast()
};
assert_eq!(0.0, result);
}
#[test]
fn test_if_f16c_is_detected() {
let detected = std::is_x86_feature_detected!("f16c");
if detected {
println!("f16c detected!");
} else {
println!("f16c not detected!");
}
assert_eq!(true, detected);
}
According to the last test (test_if_f16c_is_detected
) f16c is supportted.
Also the /proc/cpuinfo
states that f16c is supported.
I can't explain why its crashing then.
I have the feeling that its really a bug in the android emulator.
It states that the f16c
is supported, but actually fails to execute it.
Do you have experience with such kind of error?
What can I do ro reproduce it locally?
Is it related to the actual CPU? The GitHub action runner has a AMD EPYC 7763 64-Core Processor.
My machine has Intel I7.
Is the github runner running in a own VM and can the setup of VM in VM cause this issue?
We are using the reactivecircus/android-emulator-runner for creating the android virtual device.
Any hints or clues?
Is there an other way to test if the f16c instruction set is supported?
Such that we can create an error report for google?
so that we can compare by using the num_traits::assert_approx_eq
macro
assert_approx_eq!(half::f16, self.test_atomic_add_result(input), out);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ApproxEq` is not implemented for `f16`
We use half
lib extensively in our Burn project and we have a git action to build for no_std which is failing when upgrading from 2.3.1 to 2.4.0.
I recommend CI step is added specifically to test std
feature off (no_std testing) because a similar problem occurred in the past (see #84).
See errors:
Compiling bincode v2.0.0-rc.3
error: cannot find macro `vec` in this scope
--> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/half-2.4.0/src/slice.rs:368:23
|
368 | let mut vec = vec![0f32; self.len()];
| ^^^
|
help: consider importing this macro
|
10 + use alloc::vec;
|
error: cannot find macro `vec` in this scope
--> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/half-2.4.0/src/slice.rs:377:23
|
377 | let mut vec = vec![0f64; self.len()];
| ^^^
|
help: consider importing this macro
|
10 + use alloc::vec;
|
error: cannot find macro `vec` in this scope
--> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/half-2.4.0/src/slice.rs:462:23
|
462 | let mut vec = vec![0f32; self.len()];
| ^^^
|
help: consider importing this macro
|
10 + use alloc::vec;
|
error: cannot find macro `vec` in this scope
--> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/half-2.4.0/src/slice.rs:471:23
|
471 | let mut vec = vec![0f64; self.len()];
| ^^^
|
help: consider importing this macro
|
10 + use alloc::vec;
|
error: cannot find macro `vec` in this scope
--> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/half-2.4.0/src/vec.rs:139:23
|
139 | let mut vec = vec![f16::from_bits(0); slice.len()];
| ^^^
|
help: consider importing this macro
|
12 + use alloc::vec;
|
error: cannot find macro `vec` in this scope
--> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/half-2.4.0/src/vec.rs:146:23
|
146 | let mut vec = vec![f16::from_bits(0); slice.len()];
| ^^^
|
help: consider importing this macro
|
12 + use alloc::vec;
|
error: cannot find macro `vec` in this scope
--> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/half-2.4.0/src/vec.rs:[175](https://github.com/tracel-ai/burn/actions/runs/8042757366/job/21963835704?pr=1364#step:11:178):23
|
175 | let mut vec = vec![bf16::from_bits(0); slice.len()];
| ^^^
|
help: consider importing this macro
|
12 + use alloc::vec;
|
error: cannot find macro `vec` in this scope
--> /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/half-2.4.0/src/vec.rs:[182](https://github.com/tracel-ai/burn/actions/runs/8042757366/job/21963835704?pr=1364#step:11:185):23
|
182 | let mut vec = vec![bf16::from_bits(0); slice.len()];
| ^^^
|
help: consider importing this macro
|
12 + use alloc::vec;
|
In my last pull request I blindly stated that conversion of mutable slices could not be implemented because I thought it would violate mutability rules.
As it turns out, the borrow checker is really smart, and it is indeed possible to reinterpret mutable slices without incorrect behaviour. I need this functionality for efficient binary deserialization of f16
numbers.
I have implemented from_bits_mut
and to_bits_mut
in f16::slice
in my fork. I'd like to send a pull request, if you approve.
It would be really useful to have this trait implemented.
ARM provides intrinsics to convert from f32 to f16 since ARMv8, see e.g. VCVT-F16-F32
Unfortunately the Rust standard library does not implement this intrinsic yet, even though it does implement lots of similar ones - e.g. vcvt_f64_f32.
Adding support for this intrinsic in the standard library should be fairly trivial, since all the groundwork is already laid out.
We're running the half
crate's tests during our package builds in Fedora Linux and our CI has detected that since the update to Rust 1.75.0, some tests have started to fail - but only when run in --release
mode:
failures:
---- bfloat::test::test_nan_conversion_to_larger stdout ----
thread 'bfloat::test::test_nan_conversion_to_larger' panicked at src/bfloat.rs:1531:9:
assertion failed: neg_nan64_from_32.is_nan() && neg_nan64_from_32.is_sign_negative()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- bfloat::test::test_nan_conversion_to_smaller stdout ----
thread 'bfloat::test::test_nan_conversion_to_smaller' panicked at src/bfloat.rs:1502:9:
assertion failed: neg_nan32_from_64.is_nan() && neg_nan32_from_64.is_sign_negative()
---- binary16::test::test_nan_conversion_to_larger stdout ----
thread 'binary16::test::test_nan_conversion_to_larger' panicked at src/binary16.rs:1599:9:
assertion failed: neg_nan64_from_32.is_nan() && neg_nan64_from_32.is_sign_negative()
---- binary16::test::test_nan_conversion_to_smaller stdout ----
thread 'binary16::test::test_nan_conversion_to_smaller' panicked at src/binary16.rs:1570:9:
assertion failed: neg_nan32_from_64.is_nan() && neg_nan32_from_64.is_sign_negative()
failures:
bfloat::test::test_nan_conversion_to_larger
bfloat::test::test_nan_conversion_to_smaller
binary16::test::test_nan_conversion_to_larger
binary16::test::test_nan_conversion_to_smaller
Thanks for the library. Would you see it feasible to include an implementation of dtoa over a u8 mutable pointer?
Rust stabilized in 1.62 the total_cmp
method that follows the totalOrder
predicate from the IEEE754 spec (v2008, 5.10).
The same method could be added easily if it calculated the total order after converting to f32. There could also be total_cmp
& total_cmp_const
variants.
If bumping the MSRV to 1.62 is a problem, it'd be also very easy to reimplement it from scratch.
extern crate half;
use half::f16;
use std::f32;
use std::mem;
fn main() {
let nan32 = f32::NAN;
println!(
"nan32.is_sign_positive() == nan32.is_sign_negative() -> {}",
nan32.is_sign_positive() == nan32.is_sign_negative()
);
let unan32: u32 = unsafe { mem::transmute(nan32) };
let negated32: f32 = unsafe { mem::transmute(unan32 ^ 0x8000_0000) };
println!(
"nan32.is_sign_positive() == negated32.is_sign_positive() -> {}",
nan32.is_sign_positive() == negated32.is_sign_positive()
);
let nan16 = half::consts::NAN;
println!(
"nan16.is_sign_positive() == nan16.is_sign_negative() -> {}",
nan16.is_sign_positive() == nan16.is_sign_negative()
);
let unan16: u16 = unsafe { mem::transmute(nan16) };
let negated16: f16 = unsafe { mem::transmute(unan16 ^ 0x8000) };
println!(
"nan16.is_sign_positive() == negated16.is_sign_positive() -> {}",
nan16.is_sign_positive() == negated16.is_sign_positive()
);
}
Output:
nan32.is_sign_positive() == nan32.is_sign_negative() -> false
nan32.is_sign_positive() == negated32.is_sign_positive() -> false
nan16.is_sign_positive() == nan16.is_sign_negative() -> true
nan16.is_sign_positive() == negated16.is_sign_positive() -> true
Note that in Rust version 1.20.0, rust-lang/rust#42431, the behaviour of is_sign_positive
and is_sign_negative
for NaN was updated to conform to IEEE754.
Add support for the new AVX-512-BF16 x86 extension for bf16
conversions. Will need to be added to core::arch.
Extension intrinsic docs: https://www.intel.com/content/www/us/en/develop/documentation/cpp-compiler-developer-guide-and-reference/top/compiler-reference/intrinsics/intrinsics-for-avx-512-bf16-instructions.html
Please disregard, my misunderstanding of the max value the standard would represent.
extern crate half;
use half::f16;
fn main() {
let plus32 = 0f32;
let minus32 = -plus32;
let plus16 = f16::from_f32(plus32);
let minus16 = f16::from_f32(minus32);
println!("plus32 == minus32 -> {}", plus32 == minus32);
println!("plus16 == minus16 -> {}", plus16 == minus16);
println!("plus32.partial_cmp(&minus32) -> {:?}", plus32.partial_cmp(&minus32));
println!("plus16.partial_cmp(&minus16) -> {:?}", plus16.partial_cmp(&minus16));
}
Output:
plus32 == minus32 -> true
plus16 == minus16 -> false
plus32.partial_cmp(&minus32) -> Some(Equal)
plus16.partial_cmp(&minus16) -> Some(Less)
Build fails with this dependency setting:
[dependencies.half]
version = "2"
default-features = false
features = ["serde"]
Adding the "std"
feature makes the build work.
[dependencies.half]
version = "2"
default-features = false
features = ["serde", "std"]
The f64
obtained from transmuting 0x7ff0_0000_0000_0001u64
is NaN, as it has all exponent bits set and has one bit set in the mantissa. The current conversion function from f64
always discards the least significant 32 bits, so it converts this into infinity instead of NaN.
Also, for both the f32
and f64
conversion functions, the sign of a converted NaN is independent of the source, unlike the primitive conversions where the sign bit is retained when converting say from an f64
NaN to an f32
.
Github Actions CI now runs i686 and aarch64 builds like it used to, but no tests are being run for i686. Use CircleCI to do this like is being done with aarch64.
Hi!
Just started to see failures with an older msrv (1.46) with 1.8.1. https://github.com/tokio-rs/prost/runs/3976399124?check_suite_focus=true
I believe maybe it makes sense to only add resolver = 2 w/ 2021 edition update and not 1.8.1? The real solution for prost is to update to the new edition but I didn't expect this breakage.
Thanks!
Could from_f32()
etc. be const-fn? Would be useful for halving the size of float data in static arrays in demoscene intros.
I'm not able to build half
when I use it with no_std
and serde support.
Compiling half v2.2.1
error[E0599]: no method named `to_string` found for reference `&bf16` in the current scope
--> /home/nathaniel/.cargo/registry/src/github.com-1ecc6299db9ec823/half-2.2.1/src/bfloat.rs:697:40
|
697 | serializer.serialize_str(&self.to_string())
| ^^^^^^^^^ method not found in `&bf16`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
1 | use crate::alloc::string::ToString;
I use the following configuration half = {version = "2", features = ["alloc", "num-traits", "serde"], default-features = false}
I believe the fix should be easy, since it's just a missing import with those specific feature flags.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.