try_from_degrees rounds away from the nearest sixteenth at two f32 inputs
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 2/5
- Temps estimé
- 1-3 heures
- Accessibilité débutants
- 84/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Active
- Stack technique
- rust
- Domaine
- embedded-iot
Piste de recherche
Commencez dans src/lib.rs:441 et lisez les tests existants ties_round_half_away_from_zero et the_rejection_boundaries_are_exact_and_closed. Vérifiez les deux valeurs f32 signalées et l’oracle f64 documenté, puis ajoutez une couverture pour les limites internes à un demi-LSB et confirmez que try_from_degrees renvoie les valeurs arrondies documentées sans modifier le comportement de rejet.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Celsius::try_from_degrees documents its rounding as:
Values are rounded to the nearest
sixteenth of a degree, half away from zero.
src/lib.rs:404-405
It does not do that for two inputs. Both are the f32 immediately below
±1/32 — strictly nearer to zero than to one sixteenth, so both must round
to 0. Both round to ±1.
Measured
Exhaustive, not sampled: the function was transcribed verbatim into a
scratch binary and run under rustc -O against an f64 oracle over
all 2^32 f32 bit patterns.
exhaustive sweep of all 2^32 f32 inputs
TOTAL DISAGREEMENTS: 2
bits=0x3cffffff x= 3.12499981373548508e-2 driver=Ok(1) documented=Ok(0)
bits=0xbcffffff x=-3.12499981373548508e-2 driver=Ok(-1) documented=Ok(0)
The oracle applies the documented contract in f64: scale by 16 (exact),
round half away from zero, then reject if the rounded value leaves
-2048..=2047. Two disagreements, and no others anywhere in the domain.
Cause
src/lib.rs:441:
let rounded = if scaled >= 0.0 { scaled + 0.5 } else { scaled - 0.5 };
degrees * 16.0 is exact — multiplying by a power of two. The error is in
the half-add. For x = 0.031249998137354851, scaled is 0.49999997,
and 0.49999997f32 + 0.5f32 is 0.99999997 exactly, which is not
representable in binary32; it rounds to 1.0 (ties-to-even against
0.99999994). Truncation then yields 1 instead of 0.
So the tie test happens after a rounding step that can manufacture a tie
that the input did not have.
Scope
Narrow but real. try_from_degrees is the public boundary feeding
set_low_limit / set_high_limit, so an affected input programs a
threshold one LSB (0.0625 °C) away from its advertised value. The two
inputs are not values anyone types as a decimal literal; they arise from
computed floats.
This is a defect against the driver's own documented contract, not
against the datasheet — SBOS663A §7.5.2 specifies the 0.0625 °C
resolution and two's-complement format, and says nothing about how an
arbitrary float should reach a representable value. Rounding policy is
driver policy, as it is for snap_hysteresis in #76.
Why the existing tests miss it
ops_tests covers exact ties (ties_round_half_away_from_zero,
src/lib.rs:4079) and the outer rejection boundaries
(the_rejection_boundaries_are_exact_and_closed, src/lib.rs:4106).
Neither covers the representable neighbours just inside a tie, which is
precisely where the half-add misbehaves.
Options
- Round without an intermediate half-add. Compare against the tie
directly, or perform the add in a wider type. Deletes the failure mode
rather than special-casing it. - Widen to
f64for the rounding step only. One cast;no_stdsafe;
the oracle above is exactly this and is correct over the whole domain. - Document the exception. Cheapest, but the contract sentence would
have to name two specific bit patterns, which is worse than fixing it.
Any of 1 or 2 changes observable output for two inputs, so it wants a
changelog-visible commit.
Suggested test
Enumerate every internal half-LSB boundary and its two f32 neighbours
(12,285 cases) against an independent oracle, rather than a hand-picked
list. The full 2^32 sweep runs in ~2 s on 16 threads if you ever want it
as a one-off.
Provenance
Raised by the datasheet compliance audit of PR #77, then reproduced
independently. Not a regression — the behaviour predates #77; it was
simply never asserted.
- Langage dominant
- Rust
- Étoiles
- 2
- Forks
- 7
- Métriques de merge des PR
- Aucune PR mergée en 30 j
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Aucun modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de OpenDevicePartnership/tmp108
-
audit:SBOS663A bug documentation impact:field-visible verdict:contradicts
Difficulté 1/5 Moins d'une heure Accessibilité débutants 95/100
-
audit:SBOS663A bug enhancement impact:documentation
Difficulté 3/5 1-2 jours Accessibilité débutants 74/100
-
audit:SBOS663A impact:latent question verdict:unsupported
Difficulté 4/5 3-5 jours Accessibilité débutants 25/100
-
bug
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 35/100
Toutes les issues de OpenDevicePartnership/tmp108
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
cloudflare/workers-rs#1130 ·
Les mainteneurs répondent en général sous 11 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 69/100
vfarcic/dot-agent-deck#2160 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
RustCrypto/utils#1597 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
Les mainteneurs répondent en général sous 1 jour