Gets rid of a "safe" signed overflow in silk_DIV32_varQ()
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Tue, 11 Oct 2011 20:47:00 +0000 (16:47 -0400)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Tue, 11 Oct 2011 20:47:00 +0000 (16:47 -0400)
silk/Inlines.h
silk/SigProc_FIX.h

index 50060e6..765e770 100644 (file)
@@ -117,7 +117,8 @@ static inline opus_int32 silk_DIV32_varQ(    /* O    returns a good approximatio
     result = silk_SMULWB(a32_nrm, b32_inv);                                  /* Q: 29 + a_headrm - b_headrm    */
 
     /* Compute residual by subtracting product of denominator and first approximation */
-    a32_nrm -= silk_LSHIFT( silk_SMMUL(b32_nrm, result), 3 );           /* Q: a_headrm                    */
+    /* It's OK to overflow because the final value of a32_nrm should always be small */
+    a32_nrm = silk_SUB32_ovflw(a32_nrm, silk_LSHIFT_ovflw( silk_SMMUL(b32_nrm, result), 3 ));  /* Q: a_headrm                    */
 
     /* Refinement */
     result = silk_SMLAWB(result, a32_nrm, b32_inv);                          /* Q: 29 + a_headrm - b_headrm    */
index a65ac13..f9e2664 100644 (file)
@@ -417,6 +417,9 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
 /* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
    (just standard two's complement implementation-specific behaviour) */
 #define silk_ADD32_ovflw(a, b)              ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b)))
+/* Subtractss two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
+   (just standard two's complement implementation-specific behaviour) */
+#define silk_SUB32_ovflw(a, b)              ((opus_int32)((opus_uint32)(a) - (opus_uint32)(b)))
 
 /* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
 #define silk_MLA_ovflw(a32, b32, c32)       silk_ADD32_ovflw((a32), (opus_uint32)(b32) * (opus_uint32)(c32))
@@ -484,6 +487,7 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
 #define silk_LSHIFT_SAT32(a, shift)         (silk_LSHIFT32( silk_LIMIT( (a), silk_RSHIFT32( silk_int32_MIN, (shift) ),    \
                                                                           silk_RSHIFT32( silk_int32_MAX, (shift) ) ), (shift) ))
 
+#define silk_LSHIFT_ovflw(a, shift)        ((opus_int32)((opus_uint32)(a)<<(shift)))        /* shift >= 0, allowed to overflow */
 #define silk_LSHIFT_uint(a, shift)         ((a)<<(shift))        /* shift >= 0 */
 #define silk_RSHIFT_uint(a, shift)         ((a)>>(shift))        /* shift >= 0 */