Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* as_float.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS                                                                        */
  6. /*                                                                           */
  7. /* Internal Floating Point Handling                                          */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include <string.h>
  12. #include "strutil.h"
  13. #include "as_float.h"
  14.  
  15. #define DBG_MANT_APPEND 0
  16. #define DBG_MANT_ADD 0
  17.  
  18. static as_float_mant_word_t MASK(unsigned n)
  19. {
  20.   if (n < AS_FLOAT_MANT_WORD_BITS)
  21.     return ((as_float_mant_word_t)((1ul << (n)) - 1));
  22.   else
  23.     return ((as_float_mant_word_t)0) - 1;
  24. }
  25.  
  26. /*!------------------------------------------------------------------------
  27.  * \fn     as_float_get_mantissa_bit(const as_float_mant_t p_mant, unsigned num_bits, unsigned bit_pos)
  28.  * \brief  retrieve single bit of mantissa
  29.  * \param  p_mant mantissa to extract from
  30.  * \param  num_bits mantissa length
  31.  * \param  bit_pos bit position (0=MSB)
  32.  * \return 0 or 1
  33.  * ------------------------------------------------------------------------ */
  34.  
  35. Boolean as_float_get_mantissa_bit(const as_float_mant_t p_mant, unsigned num_bits, unsigned bit_pos)
  36. {
  37.   if (bit_pos >= num_bits)
  38.     return 0;
  39.   else
  40.   {
  41.     return ((p_mant[bit_pos / AS_FLOAT_MANT_WORD_BITS])
  42.          >> (AS_FLOAT_MANT_WORD_BITS_M1 - (bit_pos % AS_FLOAT_MANT_WORD_BITS))) & 1;
  43.   }
  44. }
  45.  
  46. /*!------------------------------------------------------------------------
  47.  * \fn     mantissa_used_bit_mask(unsigned mantissa_bits, unsigned word_index)
  48.  * \brief  retrieve bit mask of used mantissa bits in word #n
  49.  * \param  mantissa_bits total mantissa length in bits
  50.  * \param  word_index word index in mantissa
  51.  * \return bit mask
  52.  * ------------------------------------------------------------------------ */
  53.  
  54. static as_float_mant_word_t mantissa_used_bit_mask(unsigned mantissa_bits, unsigned word_index)
  55. {
  56.   unsigned num_words = AS_FLOAT_NUM_WORDS(mantissa_bits),
  57.            last_num_bits = mantissa_bits % AS_FLOAT_MANT_WORD_BITS;
  58.  
  59.   if (!num_words)
  60.     return 0;
  61.   else if ((word_index < num_words - 1) || !last_num_bits)
  62.     return ~((as_float_mant_word_t)0);
  63.   else
  64.     return ~MASK(AS_FLOAT_MANT_WORD_BITS - last_num_bits);
  65. }
  66.  
  67. /*!------------------------------------------------------------------------
  68.  * \fn     mantissa_add(as_float_mant_t p_sum, const as_float_mant_t p_add, const as_float_mant_t p_addend, unsigned num_bits)
  69.  * \brief  add two mantissas
  70.  * \param  p_sum sum buffer
  71.  * \param  p_add operand
  72.  * \param  p_addend addend
  73.  * \param  num_bits mantissa length
  74.  * \return carry of MSB add
  75.  * ------------------------------------------------------------------------ */
  76.  
  77. static as_float_mant_word_t mantissa_add(as_float_mant_t p_sum, const as_float_mant_t p_add, const as_float_mant_t p_addend, unsigned num_bits)
  78. {
  79.   as_float_mant_word_t carry = 0, carry1, carry2, tmp1, tmp2;
  80.   int num_words = AS_FLOAT_NUM_WORDS(num_bits);
  81.  
  82.   for (num_words--; num_words >= 0; num_words--)
  83.   {
  84.     tmp1 = p_add[num_words] + p_addend[num_words];
  85.     carry1 = tmp1 < p_add[num_words];
  86.     tmp2 = tmp1 + carry;
  87.     carry2 = tmp2 < tmp1;
  88.     p_sum[num_words] = tmp2;
  89. #if DBG_MANT_ADD
  90.     fprintf(stderr, "mantissa_add[%u] %08x %08x %u -> %08x %u\n", num_words,
  91.             (unsigned)p_add[num_words], (unsigned)p_addend[num_words], carry,
  92.             (unsigned)p_sum[num_words], carry1 | carry2);
  93. #endif
  94.     carry = carry1 | carry2;
  95.   }
  96.   return carry;
  97. }
  98.  
  99. /*!------------------------------------------------------------------------
  100.  * \fn     as_float_mantissa_add_bit(as_float_mant_t p_sum, const as_float_mant_t p_add, unsigned add_bit_pos, unsigned num_bits)
  101.  * \brief  add one bit to mantissa
  102.  * \param  p_sum sum buffer
  103.  * \param  p_add operand
  104.  * \param  add_bit_pos position of bit to add (0 = MSB)
  105.  * \param  num_bits mantissa length
  106.  * \return carry of MSB add
  107.  * ------------------------------------------------------------------------ */
  108.  
  109. as_float_mant_word_t as_float_mantissa_add_bit(as_float_mant_t p_sum, const as_float_mant_t p_add, unsigned add_bit_pos, unsigned num_bits)
  110. {
  111.   as_float_mant_t addend;
  112.  
  113.   memset(addend, 0, sizeof addend);
  114.   addend[add_bit_pos / AS_FLOAT_MANT_WORD_BITS] |= 1ul << (AS_FLOAT_MANT_WORD_BITS_M1 - (add_bit_pos % AS_FLOAT_MANT_WORD_BITS));
  115.   return mantissa_add(p_sum, p_add, addend, num_bits);
  116. }
  117.  
  118. /*!------------------------------------------------------------------------
  119.  * \fn     as_float_mantissa_shift_right(as_float_mant_t p_mantissa, as_float_mant_word_t shiftin_bit, unsigned num_bits)
  120.  * \brief  shift right mantissa one bit
  121.  * \param  p_mantissa mantissa to shift
  122.  * \param  shiftin_bit MSB to shift in from left
  123.  * \param  num_bits bit length of mantissa
  124.  * \return LSB of mantissa shifted out
  125.  * ------------------------------------------------------------------------ */
  126.  
  127. as_float_mant_word_t as_float_mantissa_shift_right(as_float_mant_t p_mantissa, as_float_mant_word_t shiftin_bit, unsigned num_bits)
  128. {
  129.   int num_words = AS_FLOAT_NUM_WORDS(num_bits), z;
  130.   unsigned last_num_bits;
  131.   as_float_mant_word_t shiftout_bit = 0;
  132.  
  133.   if (!(last_num_bits = num_bits % AS_FLOAT_MANT_WORD_BITS))
  134.     last_num_bits = AS_FLOAT_MANT_WORD_BITS;
  135.   for (z = 0; z < num_words; z++)
  136.   {
  137.     shiftout_bit = (p_mantissa[z] >> ((z == num_words - 1) ? (AS_FLOAT_MANT_WORD_BITS - last_num_bits) : 0)) & 1;
  138.     p_mantissa[z] = ((p_mantissa[z] >> 1) & MASK(AS_FLOAT_MANT_WORD_BITS_M1));
  139.     if ((z == num_words - 1) && (last_num_bits < AS_FLOAT_MANT_WORD_BITS))
  140.       p_mantissa[z] &= ~MASK(AS_FLOAT_MANT_WORD_BITS - last_num_bits);
  141.     p_mantissa[z] |= (shiftin_bit << AS_FLOAT_MANT_WORD_BITS_M1);
  142.     shiftin_bit = shiftout_bit;
  143.   }
  144.   return shiftout_bit;
  145. }
  146.  
  147. /*!------------------------------------------------------------------------
  148.  * \fn     as_float_mantissa_shift_left(as_float_mant_t p_mantissa, as_float_mant_word_t shiftin_bit, unsigned num_bits)
  149.  * \brief  shift left mantissa one bit
  150.  * \param  p_mantissa mantissa to shift
  151.  * \param  shiftin_bit MSB to shift in from right
  152.  * \param  num_bits bit length of mantissa
  153.  * \return MSB of mantissa shifted out
  154.  * ------------------------------------------------------------------------ */
  155.  
  156. as_float_mant_word_t as_float_mantissa_shift_left(as_float_mant_t p_mantissa, as_float_mant_word_t shiftin_bit, unsigned num_bits)
  157. {
  158.   int num_words = AS_FLOAT_NUM_WORDS(num_bits), z;
  159.   as_float_mant_word_t shiftout_bit = 0;
  160.  
  161.   for (z = num_words - 1; z >= 0; z--)
  162.   {
  163.     shiftout_bit = (p_mantissa[z] >> AS_FLOAT_MANT_WORD_BITS_M1) & 1;
  164.     p_mantissa[z] = ((p_mantissa[z] << 1) & (MASK(AS_FLOAT_MANT_WORD_BITS_M1) << 1));
  165.     p_mantissa[z] &= mantissa_used_bit_mask(num_bits, z);
  166.     p_mantissa[z] |= shiftin_bit;
  167.     shiftin_bit = shiftout_bit;
  168.   }
  169.   return shiftout_bit;
  170. }
  171.  
  172. /*!------------------------------------------------------------------------
  173.  * \fn     as_float_mantissa_is_zero_from(const as_float_dissect_t *p_num, unsigned start_bit)
  174.  * \brief  is mantissa all-zeros, starting at given bit?
  175.  * \param  p_num number to check
  176.  * \param  start_bit starting bit position
  177.  * \return True if zero
  178.  * ------------------------------------------------------------------------ */
  179.  
  180. Boolean as_float_mantissa_is_zero_from(const as_float_dissect_t *p_num, unsigned start_bit)
  181. {
  182.   if (start_bit < p_num->mantissa_bits)
  183.   {
  184.     as_float_mant_word_t sum = 0, mask;
  185.     unsigned num_words = AS_FLOAT_NUM_WORDS(p_num->mantissa_bits), z,
  186.              start_word = start_bit / AS_FLOAT_MANT_WORD_BITS,
  187.              start_bit_in_word = start_bit % AS_FLOAT_MANT_WORD_BITS;
  188.  
  189.     for (z = start_word; z < num_words; z++)
  190.     {
  191.       mask = mantissa_used_bit_mask(p_num->mantissa_bits, z);
  192.       if ((z == start_word) && start_bit_in_word)
  193.         mask &= MASK(AS_FLOAT_MANT_WORD_BITS - start_bit_in_word);
  194.       sum |= p_num->mantissa[z] & mask;
  195.     }
  196.     return !sum;
  197.   }
  198.   else
  199.     return True;
  200. }
  201.  
  202. /*!------------------------------------------------------------------------
  203.  * \fn     as_float_mantissa_is_allones_from(const as_float_dissect_t *p_num, unsigned start_bit)
  204.  * \brief  is mantissa all-ones, starting at given bit?
  205.  * \param  p_num number to check
  206.  * \param  start_bit starting bit position
  207.  * \return True if zero
  208.  * ------------------------------------------------------------------------ */
  209.  
  210. Boolean as_float_mantissa_is_allones_from(const as_float_dissect_t *p_num, unsigned start_bit)
  211. {
  212.   if (start_bit < p_num->mantissa_bits)
  213.   {
  214.     unsigned num_words = AS_FLOAT_NUM_WORDS(p_num->mantissa_bits), z,
  215.              start_word = start_bit / AS_FLOAT_MANT_WORD_BITS,
  216.              start_bit_in_word = start_bit % AS_FLOAT_MANT_WORD_BITS;
  217.     as_float_mant_word_t mask;
  218.  
  219.     for (z = start_word; z < num_words; z++)
  220.     {
  221.       mask = mantissa_used_bit_mask(p_num->mantissa_bits, z);
  222.       if ((z == start_word) && start_bit_in_word)
  223.         mask &= MASK(AS_FLOAT_MANT_WORD_BITS - start_bit_in_word);
  224.       if ((p_num->mantissa[z] & mask) != mask)
  225.         return False;
  226.     }
  227.     return True;
  228.   }
  229.   else
  230.     return False;
  231. }
  232.  
  233. /*!------------------------------------------------------------------------
  234.  * \fn     as_float_mantissa_extract(const as_float_dissect_t *p_num, unsigned start_bit, unsigned num_bits)
  235.  * \brief  extract bit field from mantissa
  236.  * \param  p_num mantissa source
  237.  * \param  start_bit start (highest, leftmost) position
  238.  * \param  num_bits bit field length
  239.  * \return extracted field
  240.  * ------------------------------------------------------------------------ */
  241.  
  242. LongWord as_float_mantissa_extract(const as_float_dissect_t *p_num, unsigned start_bit, unsigned num_bits)
  243. {
  244.   LongWord ret = 0;
  245.   unsigned this_num_bits, this_word, end_bit, max_end_bit;
  246.  
  247.   if ((start_bit >= p_num->mantissa_bits)
  248.    || (start_bit + num_bits > p_num->mantissa_bits))
  249.     return ret;
  250.  
  251.   while (num_bits > 0)
  252.   {
  253.     this_word = start_bit / AS_FLOAT_MANT_WORD_BITS;
  254.     end_bit = start_bit + num_bits;
  255.     max_end_bit = start_bit + (AS_FLOAT_MANT_WORD_BITS - (start_bit % AS_FLOAT_MANT_WORD_BITS));
  256.     if (end_bit > max_end_bit)
  257.       end_bit = max_end_bit;
  258.     this_num_bits = end_bit - start_bit;
  259.     ret = (ret << this_num_bits) | ((p_num->mantissa[this_word] >> (max_end_bit - end_bit)) & MASK(this_num_bits));
  260.     start_bit += this_num_bits;
  261.     num_bits -= this_num_bits;
  262.   }
  263.   return ret;
  264. }
  265.  
  266. /*!------------------------------------------------------------------------
  267.  * \fn     as_float_zero(as_float_dissect_t *p_dest)
  268.  * \brief  initialize / zero dissected fload
  269.  * \param  p_dest what to init
  270.  * ------------------------------------------------------------------------ */
  271.  
  272. void as_float_zero(as_float_dissect_t *p_dest)
  273. {
  274.   p_dest->fp_class = AS_FP_NORMAL;
  275.   p_dest->negative = False;
  276.   p_dest->exponent = 0;
  277.   p_dest->mantissa_bits = 0;
  278.   memset (p_dest->mantissa, 0, sizeof p_dest->mantissa);
  279. }
  280.  
  281. /*!------------------------------------------------------------------------
  282.  * \fn     as_float_mantissa_twos_complement(as_float_dissect_t *p_num)
  283.  * \brief  transform mantissa into two's complement
  284.  * \param  p_num number to transform
  285.  * ------------------------------------------------------------------------ */
  286.  
  287. void as_float_mantissa_twos_complement(as_float_dissect_t *p_num)
  288. {
  289.   /* mantissa becomes one bit longer, due to the leading sign bit */
  290.  
  291.   as_float_append_mantissa_bits(p_num, 0, 1);
  292.   as_float_mantissa_shift_right(p_num->mantissa, 0, p_num->mantissa_bits);
  293.   if (p_num->negative)
  294.   {
  295.     unsigned num_words = AS_FLOAT_NUM_WORDS(p_num->mantissa_bits), z;
  296.  
  297.     for (z = 0; z < num_words; z++)
  298.     {
  299.       as_float_mant_word_t mask = mantissa_used_bit_mask(p_num->mantissa_bits, z);
  300.       p_num->mantissa[z] = (p_num->mantissa[z] ^ mask) & mask;
  301.     }
  302.     as_float_mantissa_add_bit(p_num->mantissa, p_num->mantissa, p_num->mantissa_bits - 1, p_num->mantissa_bits);
  303.     p_num->negative = False;
  304.   }
  305. }
  306.  
  307. /*!------------------------------------------------------------------------
  308.  * \fn     as_float_append_mantissa_bits(as_float_dissect_t *p_dest, LongWord new_bits, unsigned new_num_bits)
  309.  * \brief  extend mantissa of dissected float
  310.  * \param  p_dest what to extend
  311.  * \param  new_bits bits to append
  312.  * \param  new_num_bits how many bits to append from new_bits?
  313.  * ------------------------------------------------------------------------ */
  314.  
  315. extern void as_float_append_mantissa_bits(as_float_dissect_t *p_dest, LongWord new_bits, unsigned new_num_bits)
  316. {
  317. #if DBG_MANT_APPEND
  318.   fprintf(stderr, "append_mantissa_bits %u curr %u\n", new_num_bits, p_dest->mantissa_bits);
  319. #endif
  320.   while (new_num_bits > 0)
  321.   {
  322.     unsigned rem_num_bits = AS_FLOAT_MANT_WORD_BITS - (p_dest->mantissa_bits & AS_FLOAT_MANT_WORD_BITS_M1),
  323.              this_num_bits = (rem_num_bits < new_num_bits) ? rem_num_bits : new_num_bits,
  324.              dest_pos = rem_num_bits - this_num_bits,
  325.              src_pos = new_num_bits - this_num_bits,
  326.              lowest_mantissa = p_dest->mantissa_bits / AS_FLOAT_MANT_WORD_BITS;
  327.     if (AS_FLOAT_MANT_WORD_BITS == rem_num_bits)
  328.       p_dest->mantissa[lowest_mantissa] = (as_float_mant_word_t)0;
  329.  
  330. #if DBG_MANT_APPEND
  331.     fprintf(stderr, " append %u from %u to %u\n", this_num_bits, src_pos, dest_pos);
  332. #endif
  333.     p_dest->mantissa[lowest_mantissa] |= ((new_bits >> src_pos) & MASK(this_num_bits)) << dest_pos;
  334.  
  335.     new_num_bits -= this_num_bits;
  336.     p_dest->mantissa_bits += this_num_bits;
  337.   }
  338. }
  339.  
  340. /*!------------------------------------------------------------------------
  341.  * \fn     as_float_remove_mantissa_bits(as_float_dissect_t *p_num, unsigned remove_num_bits)
  342.  * \brief  remove given # of bits from mantissa at end
  343.  * \param  p_num number to modify
  344.  * \param  remove_num_bits # of bits to remove
  345.  * ------------------------------------------------------------------------ */
  346.  
  347. void as_float_remove_mantissa_bits(as_float_dissect_t *p_num, unsigned remove_num_bits)
  348. {
  349.   unsigned new_num_bits, new_num_words, this_num_words, last_num_bits;
  350.  
  351.   if (!p_num->mantissa_bits)
  352.     return;
  353.   if (remove_num_bits >= p_num->mantissa_bits)
  354.     remove_num_bits = p_num->mantissa_bits - 1;
  355.  
  356.   new_num_bits = p_num->mantissa_bits - remove_num_bits;
  357.   new_num_words = AS_FLOAT_NUM_WORDS(new_num_bits);
  358.   this_num_words = AS_FLOAT_NUM_WORDS(p_num->mantissa_bits);
  359.   if (new_num_words < this_num_words)
  360.     memset(&p_num->mantissa[new_num_words], 0, (this_num_words - new_num_words) * sizeof(*p_num->mantissa));
  361.   last_num_bits = new_num_bits % AS_FLOAT_MANT_WORD_BITS;
  362.   if (last_num_bits)
  363.     p_num->mantissa[new_num_words - 1] &= ~MASK(AS_FLOAT_MANT_WORD_BITS - last_num_bits);
  364.   p_num->mantissa_bits = new_num_bits;
  365. }
  366.  
  367. /*!------------------------------------------------------------------------
  368.  * \fn     void as_float_round(as_float_dissect_t *p_num, unsigned target_bits)
  369.  * \brief  round/extend float to the given number of mantissa bits
  370.  * \param  p_num number to round
  371.  * \param  target_bits # of mantissa bits to achieve
  372.  * \return type of rounding performed
  373.  * ------------------------------------------------------------------------ */
  374.  
  375. as_float_round_t as_float_round(as_float_dissect_t *p_num, unsigned target_bits)
  376. {
  377.   as_float_round_t round_type = e_round_none;
  378.  
  379.   /* if the current mantissa is shorter, append zeros: */
  380.  
  381.   while (p_num->mantissa_bits < target_bits)
  382.   {
  383.     unsigned delta = target_bits - p_num->mantissa_bits;
  384.  
  385.     if (delta > AS_FLOAT_MANT_WORD_BITS)
  386.       delta = AS_FLOAT_MANT_WORD_BITS;
  387.     as_float_append_mantissa_bits(p_num, 0, delta);
  388.   }
  389.  
  390.   /* Rounding: round-to-the nearest: */
  391.  
  392.   if (p_num->mantissa_bits > target_bits)
  393.   {
  394.     /* The bit representing 0.5 digits is zero: fractional part is < 0.5, round down */
  395.  
  396.     if (!as_float_get_mantissa_bit(p_num->mantissa, p_num->mantissa_bits, target_bits));
  397.     else
  398.     {
  399.       /* any lower bit in fraction is also set: fractional part is > 0.5, round up */
  400.  
  401.       if (!as_float_mantissa_is_zero_from(p_num, target_bits + 1))
  402.         round_type = e_round_up;
  403.  
  404.       /* fractional part is exactly 0.5: round towards even, i.e if mantissa part to be kept is odd: */
  405.  
  406.       else if (as_float_get_mantissa_bit(p_num->mantissa, p_num->mantissa_bits, target_bits - 1))
  407.         round_type = e_round_up;
  408.     }
  409.  
  410.     if (round_type == e_round_up)
  411.     {
  412.       as_float_mant_t sum;
  413.       as_float_mant_word_t carry;
  414.  
  415.       /* round up: add 0.5 LSB: */
  416.  
  417.       carry = as_float_mantissa_add_bit(sum, p_num->mantissa, target_bits, p_num->mantissa_bits);
  418.  
  419.       /* shift mantissa if carry: */
  420.  
  421.       if (carry)
  422.       {
  423.         as_float_mantissa_shift_right(sum, carry, p_num->mantissa_bits);
  424.         p_num->exponent++;
  425.       }
  426.       memcpy(p_num->mantissa, sum, sizeof p_num->mantissa);
  427.     }
  428.  
  429.     /* Store whether we are actually rounding down of just truncating zeros: */
  430.  
  431.     else if (!as_float_mantissa_is_zero_from(p_num, target_bits + 1))
  432.       round_type = e_round_down;
  433.  
  434.     /* Truncate mantissa after possible rounding */
  435.  
  436.     as_float_remove_mantissa_bits(p_num, p_num->mantissa_bits - target_bits);
  437.   }
  438.  
  439.   return round_type;
  440. }
  441.  
  442. /*!------------------------------------------------------------------------
  443.  * \fn     as_float_dump_mantissa(FILE *p_dest, const as_float_mant_t p_mantissa, unsigned mantissa_bits)
  444.  * \brief  dump mantissa of as_float_dissect_t
  445.  * \param  p_mantissa mantissa bits
  446.  * \param  mantissa_bits mantissa length
  447.  * ------------------------------------------------------------------------ */
  448.  
  449. void as_float_dump_mantissa(FILE *p_dest, const as_float_mant_t p_mantissa, unsigned mantissa_bits)
  450. {
  451.   unsigned mant_idx, num_mant_words = AS_FLOAT_NUM_WORDS(mantissa_bits),
  452.            num_last_bits = mantissa_bits % AS_FLOAT_MANT_WORD_BITS;
  453.   char str[20];
  454.  
  455.   for (mant_idx = 0; mant_idx < num_mant_words; mant_idx++)
  456.   {
  457.     as_snprintf(str, sizeof str, "%0*lx", AS_FLOAT_MANT_WORD_BITS / 4, (unsigned long)p_mantissa[mant_idx]);
  458.     if ((mant_idx == num_mant_words - 1) && num_last_bits)
  459.       str[(num_last_bits + 3) / 4] = '\0';
  460.     fprintf(p_dest, " %s", str);
  461.   }
  462.   fprintf(p_dest, " (%u)", mantissa_bits);
  463. }
  464.  
  465. /*!------------------------------------------------------------------------
  466.  * \fn     as_float_dump(FILE *p_dest, const char *p_name, const as_float_dissect_t *p_float)
  467.  * \brief  dump contents of dissected float
  468.  * \param  p_dest where to dump
  469.  * \param  p_name optional title
  470.  * \param  p_float what to dump
  471.  * ------------------------------------------------------------------------ */
  472.  
  473. void as_float_dump(FILE *p_dest, const char *p_name, const as_float_dissect_t *p_float)
  474. {
  475.   if (p_name)
  476.     fprintf(p_dest, "%s: ", p_name);
  477.   fprintf(p_dest, "negative %u exp %d mant", p_float->negative, p_float->exponent);
  478.   as_float_dump_mantissa(p_dest, p_float->mantissa, p_float->mantissa_bits);
  479.   fprintf(p_dest, "\n");
  480. }
  481.