From be0fd36bf575890e416820a7f4c8745c92c20bcc Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 2 Sep 2020 12:58:28 +0200 Subject: [PATCH] const_fixed_from_int implementation that works on rustc 1.44 --- src/lib.rs | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 64a3b63..0ecec91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -590,27 +590,14 @@ fixed! { #[macro_export] macro_rules! const_fixed_from_int { ($(const $NAME:ident: $Fixed:ty = $int:expr;)*) => { $( - const $NAME: $Fixed = <$Fixed>::from_bits({ - let int = $int; - // 0 should work even for no integer bits. - if int == 0 { - // Use int here to clearly ensure that the type of int is the inner type. - int - } else { - // Fails to compile if int is not zero and there are no integer bits. - let one_bits = <$Fixed>::from_bits(1).to_bits() << <$Fixed>::FRAC_NBITS; - if one_bits > 0 { - // one_bits is positive: multiplication overflows if int does not fit. - int * one_bits - } else if !int == 0 { - // one_bits is negative minimum for signed inner type and int is -1. - one_bits - } else { - // one_bits is negative minimum and int is not 0 or -1: overflow. - 1 / 0 - } - } - }); + const $NAME: $Fixed = { + const FRAC: u32 = <$Fixed>::FRAC_NBITS; + // Divide shift into two parts for cases where $Fixed cannot represent 1. + // Use $Fixed as type because there isn't a const way to get the inner type. + const ONE_A: $Fixed = <$Fixed>::from_bits(1 << FRAC / 2); + const ONE_B: $Fixed = <$Fixed>::from_bits(1 << FRAC - FRAC / 2); + <$Fixed>::from_bits($int * ONE_A.to_bits() * ONE_B.to_bits()) + }; )* }; }