• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 409
  • Last Modified:

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!
0
CoolJFN
Asked:
CoolJFN
  • 2
1 Solution
 
nikhileduCommented:
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;
}

Open in new window

0
 
Infinity08Commented:
>> 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

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now