This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

IQMath and negative zero

Other Parts Discussed in Thread: TMS320DM6435

I am having a problem working with "negative zero" and the IQMath library.  In particular, float negative zero isn't surviving a round trip conversion.

Does anyone have any suggestions on how to work in a scenario when your floats could be negative zero?

Here is an example that demonstrates the behavior in debug mode (-g -mi1 -mv6400+ -d"_DEBUG")  (in release mode I am guessing there was some optimization that was making negZero just be +0).  I have not chosen a "Floating Point mode" in the build compiler options.

#include "IQmath.h"
#include <stdio.h>

int main()
{
    float const zero = 0.0f;
    float const negZero = -zero;
    _iq21 const negZeroIq = _FtoIQ21(negZero);
    float const negZeroIqFl = _IQ21toF(negZeroIq);

    unsigned int const negZero_bytes = *reinterpret_cast<unsigned int const *>(&negZero);
    unsigned int const negZeroIq_bytes = *reinterpret_cast<unsigned int const *>(&negZeroIq);
    unsigned int const negZeroIqFl_bytes = *reinterpret_cast<unsigned int const *>(&negZeroIq);
   
    printf("negZero: %f (%u) -> %d (%u) -> %f (%u)\n", double(negZero), negZero_bytes, negZeroIq, negZeroIq_bytes, double(negZeroIqFl), negZeroIqFl_bytes);

    return 0;
}

Basically float negative zero is represented by the bytes 0x80000000.  I believe it is the logic inside _FtoIQN that gives me a problem when dealing with this value.

IQMath release ver 2.1.4

TMS320DM6435

Code Composer 3.3.82.13, Integrated Development 5.98.0.393 TI, BIOS 5.41.02.14, Code Generation Tools v6.1.20, Board Revision (00.00.84), Target Silicon Revision (00.00.02)

 

Here is the inline of _FtoIQN for easy reference:

/*;;###########################################################################
;;
;; FILE:    FtoIQN.c
;;
;; TITLE:   C Callable IQ to Float Math Function
;;
;;===========================================================================
;; Function:   _FtoIQN
;;===========================================================================
;;
;; C Usage:    extern int _FtoIQ(float A);   // no round or sat
;;
;;---------------------------------------------------------------------------
;;
;; On Entry:   A4    = IEEE 754 floating-point equivalent of A
;; On Exit:    A4    = A in IQ format
;;                      
;; Q range:    31 to 1
;;
;;---------------------------------------------------------------------------
;; Algorithm:  This operation converts an IEEE 754 Single-Precision
;;             floating-point number to equivalent IQ number. This
;;             format is shown below:
;;
;;              31  30        23 22                                 0
;;             +-----------------------------------------------------+
;;             | s |      e     |                 f                  |
;;             +-----------------------------------------------------+
;;
;;             Value = (-1)^s * 2^(e-127) * 1.f
;;
;;             where: e = 1 to 254, f = 0.000000000 to ~1.0
;;                    e = 0, f = 0, s = 0, Value = 0.0
;;                    e = 0 and f != 0 case cannot occur in IQ math
;;                    e = 255 case cannot occur in IQ math
;;         
;;--------------------------------------------------------------------------*/

 

static inline I32_IQ _FtoIQN(float input, U32_IQ qfmt)
{
#ifdef _TMS320C6X

    U32_IQ al, x, temp1, temp2, sbits, e, imp=1;
    I32_IQ ah;
    x = _ftoi(input);     // Re-interprits the bits in float as an unsigned int
    temp2 = x & 0xc0000000u;        //stores the sign and hidden bit
    if(x == 0)
    {
        imp = 0;
    }

    /* ======================================================================== */
    /*  extract the exponent(sbits) & hidden bit                                */
    /* ======================================================================== */
   
    sbits = _extu(x, 1u, 24u);
    if(sbits < 128u)
    {
        temp2 = temp2 ^ 0x40000000u;
    }

    /* ======================================================================== */
    /*  find the no. of bits by which the final result has to be shiftehd        */
    /* ======================================================================== */
   
    e = 127u + (30u - qfmt);
    sbits = e - sbits;

    /* ======================================================================== */
    /*  arrange for representtion in Q-Format                                   */
    /* ======================================================================== */

    temp1 = x & 0x07fffffu;
    al = temp1;
    al = al << 7u;
    al = al | temp2;

    /* ======================================================================== */
    /*  if then sign is -ve complement the bits except sign bit                 */
    /* ======================================================================== */

    if(((temp2 >> 31u) != 0) && (temp1 != 0u))
    {
        al = al ^ 0x7fffff80u;
    }
    ah = (I32_IQ)al;
    ah =  ((I32_IQ)ah >> sbits);    //shift right by sbits
    ah = ah * (I32_IQ)imp;
    return(ah);

#else /* For host. (since no equivalent of _ftoIQ() exists */
    I32_IQ res;
    res = input * (1 << qfmt);
    return(res);
#endif /* _TMS320C6X */

}