try_from_degrees rounds away from the nearest sixteenth at two f32 inputs
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 2/5
- Tempo estimado
- 1-3 horas
- Facilidade para iniciantes
- 84/100
- Tipo de issue
- Bug
- Clareza
- Claramente especificada
- Status de atividade
- Ativa
- Stack de tecnologia
- rust
- Domínio
- embedded-iot
Direção de pesquisa
Comece em src/lib.rs:441 e leia os testes existentes ties_round_half_away_from_zero e the_rejection_boundaries_are_exact_and_closed. Verifique os dois valores f32 reportados e o oráculo f64 documentado; em seguida, adicione cobertura para os limites internos de meio LSB e confirme que try_from_degrees retorna os valores arredondados documentados sem alterar o comportamento de rejeição.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
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.
- Linguagem predominante
- Rust
- Estrelas
- 2
- Forks
- 7
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Sem modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de OpenDevicePartnership/tmp108
-
audit:SBOS663A bug documentation impact:field-visible verdict:contradicts
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 95/100
-
audit:SBOS663A bug enhancement impact:documentation
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 74/100
-
audit:SBOS663A impact:latent question verdict:unsupported
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 25/100
-
bug
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 35/100
Todas as issues de OpenDevicePartnership/tmp108
Issues semelhantes
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 69/100
bytecodealliance/rustix#1736 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
longbridge/gpui-kit#3871 ·
Mantenedores costumam responder em até 1 dia
-
area:models enhancement
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 77/100
Mantenedores costumam responder em até 1 dia
-
fix v1 repository metadataAbertagood first issue help wanted
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 84/100
servo/rust-smallvec#864 ·