mul_mod_special is documented as computing multiplication modulo the special modulus p = MAX + 1 - c, i.e. 2^bits - c.
When c = 0, that modulus is 2^bits, so the expected result is ordinary fixed-width wrapping multiplication:
(a * b) mod 2^bits == a.wrapping_mul(b)
The one-limb fixed and boxed implementations instead reach a reduction path that constructs NonZero<Limb> from 0:
NonZero::<Limb>::new_unwrap(Limb::ZERO.wrapping_sub(c))
With c = 0, this panics with invalid value: zero. This affects Uint<1>::mul_mod_special and one-limb BoxedUint::mul_mod_special. Wider inputs already naturally behave like wrapping multiplication for this c = 0 power-of-two modulus case.
Expected behavior: mul_mod_special(..., Limb::ZERO) should return the same value as wrapping_mul for the same precision.
mul_mod_specialis documented as computing multiplication modulo the special modulusp = MAX + 1 - c, i.e.2^bits - c.When
c = 0, that modulus is2^bits, so the expected result is ordinary fixed-width wrapping multiplication:The one-limb fixed and boxed implementations instead reach a reduction path that constructs
NonZero<Limb>from0:With
c = 0, this panics withinvalid value: zero. This affectsUint<1>::mul_mod_specialand one-limbBoxedUint::mul_mod_special. Wider inputs already naturally behave like wrapping multiplication for thisc = 0power-of-two modulus case.Expected behavior:
mul_mod_special(..., Limb::ZERO)should return the same value aswrapping_mulfor the same precision.