Skip to content
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

OrderedFloat refactor #918

Merged
merged 3 commits into from
Dec 11, 2021
Merged

OrderedFloat refactor #918

merged 3 commits into from
Dec 11, 2021

Conversation

Bromeon
Copy link
Contributor

@Bromeon Bromeon commented Nov 29, 2021

Following #863 (comment), this moves egui/util/float_ord.rs -> epaint/util/ordered_float.rs and implements Hash based on epaint::f32_hash().

Open questions:

  1. Currently, f64::ord() simply truncates to f32, which may yield incorrect results for high precision floats. I see three solutions:

    • Make OrderedFloat generic on the float type. A bit more complex implementation, as we need to create traits to abstract over f32 and f64 for is_nan() etc.
    • Use always f32 (status quo) -- not recommended, can cause really nasty bugs
    • Use always f64 -- safe, but might incur minor performance penalty
  2. Should this be part of the public API?
    I moved it to a different crate, so it can't be pub(crate) anymore. However, we can mark it #[doc(hidden)] if it should stay an implementation detail.

@emilk
Copy link
Owner

emilk commented Nov 29, 2021

Let's keep it f32 only until a need for f64 actually arises. Then we can make it generic.

It's fine if it's part of the public API imho - it is hidden enough in mod util

@Bromeon
Copy link
Contributor Author

Bromeon commented Nov 29, 2021

There's currently one occurrence already:

https://github.com/emilk/egui/blob/master/egui/src/widgets/plot/items/mod.rs#L1309
The field Bar::value is of type f64, for consistency with the X/Y values.

let new_base_offset = if bar.value.is_sign_positive() {
    others
        .iter()
        .filter_map(|other_chart| other_chart.bars.get(index).map(|bar| bar.upper()))
        .max_by_key(|value| value.ord())
} else {
    others
        .iter()
        .filter_map(|other_chart| other_chart.bars.get(index).map(|bar| bar.lower()))
        .min_by_key(|value| value.ord())
};

@emilk
Copy link
Owner

emilk commented Nov 29, 2021

Oh right! Then I suggest either OrderedFloat<T> or OrderedF32/OrderedF64 (probably simpler).

@Bromeon
Copy link
Contributor Author

Bromeon commented Nov 29, 2021

Went for OrderedFloat<T>, with T: Float as an internal bound. Float is a minimalistic generalization of f32 and f64 with just hash() and is_nan() for now; could be extended if other parts of the library need it.

Hash for OrderedFloat<f64> needed a hash implementation; I copied f32_hash() and adjusted it for f64. Let me know if I should implement this differently!

Also added some documentation and a usage example.

@Bromeon Bromeon marked this pull request as ready for review November 29, 2021 22:19
@emilk emilk merged commit 5ec1486 into emilk:master Dec 11, 2021
@Bromeon Bromeon deleted the refactor/ordered-float branch December 11, 2021 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants