Skip to content

[naga]: Add no_std polyfill for round_ties_even for f32 and f64 #7585

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,11 @@ jobs:

# check with no features
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p wgpu-types --no-default-features
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p naga --no-default-features

# Check with all features except "std".
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p wgpu-types --no-default-features --features strict_asserts,fragile-send-sync-non-atomic-wasm,serde,counters
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p naga --no-default-features --features dot-out,compact

# Building for native platforms with standard tests.
- name: Check native
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Bottom level categories:

#### Naga

- Added `no_std` support with default features disabled. By @Bushrat011899 in [#7585](https://github.com/gfx-rs/wgpu/pull/7585).

### Bux Fixes

#### Naga
Expand Down
7 changes: 7 additions & 0 deletions naga/src/back/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ pub type NeedBakeExpressions = crate::FastHashSet<crate::Handle<crate::Expressio
///
/// [`Expression`]: crate::Expression
/// [`Handle`]: crate::Handle
#[cfg_attr(
not(any(glsl_out, hlsl_out, msl_out, wgsl_out)),
allow(
dead_code,
reason = "shared helpers can be dead if none of the enabled backends need it"
)
)]
struct Baked(crate::Handle<crate::Expression>);

impl core::fmt::Display for Baked {
Expand Down
64 changes: 38 additions & 26 deletions naga/src/proc/constant_evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1171,34 +1171,46 @@ impl<'a> ConstantEvaluator<'a> {
component_wise_float!(self, span, [arg], |e| { Ok([e.floor()]) })
}
crate::MathFunction::Round => {
component_wise_float(self, span, [arg], |e| match e {
Float::Abstract([e]) => Ok(Float::Abstract([e.round_ties_even()])),
Float::F32([e]) => Ok(Float::F32([e.round_ties_even()])),
Float::F16([e]) => {
// TODO: `round_ties_even` is not available on `half::f16` yet.
//
// This polyfill is shamelessly [~~stolen from~~ inspired by `ndarray-image`][polyfill source],
// which has licensing compatible with ours. See also
// <https://github.com/rust-lang/rust/issues/96710>.
//
// [polyfill source]: https://github.com/imeka/ndarray-ndimage/blob/8b14b4d6ecfbc96a8a052f802e342a7049c68d8f/src/lib.rs#L98
fn round_ties_even(x: f64) -> f64 {
let i = x as i64;
let f = (x - i as f64).abs();
if f == 0.5 {
if i & 1 == 1 {
// -1.5, 1.5, 3.5, ...
(x.abs() + 0.5).copysign(x)
} else {
(x.abs() - 0.5).copysign(x)
}
} else {
x.round()
}
}
/// Rounds to the nearest integer, with ties biasing towards an even result.
///
/// # TODO
///
/// - `round_ties_even` is not available on `half::f16` yet.
/// - It is also not available on `no_std`
///
/// This polyfill is shamelessly [~~stolen from~~ inspired by `ndarray-image`][polyfill source],
/// which has licensing compatible with ours. See also
/// <https://github.com/rust-lang/rust/issues/96710>.
///
/// [polyfill source]: https://github.com/imeka/ndarray-ndimage/blob/8b14b4d6ecfbc96a8a052f802e342a7049c68d8f/src/lib.rs#L98
fn round_ties_even<T: num_traits::float::FloatCore>(x: T) -> T {
let half = (T::one() + T::one()).recip();

if x.fract().abs() != half {
x.round()
} else {
let i = x.abs().trunc();

Ok(Float::F16([(f16::from_f64(round_ties_even(f64::from(e))))]))
let value = if (i * half).fract() == half {
// -1.5, 1.5, 3.5, ...
x.abs() + half
} else {
// -0.5, 0.5, 2.5, ...
x.abs() - half
};

if x.signum() != value.signum() {
-value
} else {
value
}
}
}

component_wise_float(self, span, [arg], |e| match e {
Float::Abstract([e]) => Ok(Float::Abstract([round_ties_even(e)])),
Float::F32([e]) => Ok(Float::F32([round_ties_even(e)])),
Float::F16([e]) => Ok(Float::F16([round_ties_even(e)])),
})
}
crate::MathFunction::Fract => {
Expand Down
Loading