# How do I convert the comp_t data type to a float in C, given its encoding?

I need to convert the Linux C comp_t data type to a float, or something else I can print out. The description of this type is

/*
*  comp_t is a 16-bit "floating" point number with a 3-bit base 8
*  exponent and a 13-bit fraction. See linux/kernel/acct.c for the
*  specific encoding system used.
*/

typedef __u16   comp_t;

I have looked up the encoding function, but still do not know how I can decode it (i.e., convert to a standard data type):

224 /*
225  *  encode an unsigned long into a comp_t
226  *
227  *  This routine has been adopted from the encode_comp_t() function in
228  *  the kern_acct.c file of the FreeBSD operating system. The encoding
229  *  is a 13-bit fraction with a 3-bit (base 8) exponent.
230  */
231
232 #define MANTSIZE        13                      /* 13 bit mantissa. */
233 #define EXPSIZE         3                       /* Base 8 (3 bit) exponent. */
234 #define MAXFRACT        ((1 << MANTSIZE) - 1)   /* Maximum fractional value. */
235
236 static comp_t encode_comp_t(unsigned long value)
237 {
238         int exp, rnd;
239
240         exp = rnd = 0;
241         while (value > MAXFRACT) {
242                 rnd = value & (1 << (EXPSIZE - 1));     /* Round up? */
243                 value >>= EXPSIZE;      /* Base 8 exponent == 3 bit shift. */
244                 exp++;
245         }
246
247         /*
248          * If we need to round up, do it (and handle overflow correctly).
249          */
250         if (rnd && (++value > MAXFRACT)) {
251                 value >>= EXPSIZE;
252                 exp++;
253         }
254
255         /*
256          * Clean it up and polish it off.
257          */
258         exp <<= MANTSIZE;               /* Shift the exponent into place */
259         exp += value;                   /* and add on the mantissa. */
260         return exp;
261 }

What would be a function to convert it back? THANKS!
###### Who is Participating?

Commented:
0

Commented:
A possible solution is to extract the fractional components for the mantissa and the exponent from the bits encoded in the comp_t value supplied and to create a double number from these fractional components. This algorithm is coded in the function comp_t_to_double() as given below.

/* This function converts from comp_t to double value for exponent base 10. */
double comp_t_to_double(comp_t value)
{
double dval = 0;
int exp = 0;

/*
* Get the fraction components.
*/
exp = value >> MANTSIZE;        /* Get the exponent (first 3 bits). */
dval = (value & MAXFRACT);        /* Get the mantissa (last 13 bits). */

for(int i=0; i < exp; i++) {
dval /= 10;
}

return dval;
}
0

Commented:
>> What would be a function to convert it back?

Right from the docs :

comp_t c;
unsigned long v = (c & 0x1fff) << (((c >> 13) & 0x7) * 3);

converts the comp_t value c to an unsigned long value v.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.