Back to index

cell-binutils  2.17cvs20070401
Functions
flonum-mult.c File Reference
#include "ansidecl.h"
#include "flonum.h"

Go to the source code of this file.

Functions

void flonum_multip (const FLONUM_TYPE *a, const FLONUM_TYPE *b, FLONUM_TYPE *product)

Function Documentation

void flonum_multip ( const FLONUM_TYPE *  a,
const FLONUM_TYPE *  b,
FLONUM_TYPE *  product 
)

Definition at line 74 of file flonum-mult.c.

{
  int size_of_a;            /* 0 origin  */
  int size_of_b;            /* 0 origin  */
  int size_of_product;             /* 0 origin  */
  int size_of_sum;          /* 0 origin  */
  int extra_product_positions;     /* 1 origin  */
  unsigned long work;
  unsigned long carry;
  long exponent;
  LITTLENUM_TYPE *q;
  long significant;         /* TRUE when we emit a non-0 littlenum  */
  /* ForTran accent follows.  */
  int P;                    /* Scan product low-order -> high.  */
  int N;                    /* As in sum above.  */
  int A;                    /* Which [] of a?  */
  int B;                    /* Which [] of b?  */

  if ((a->sign != '-' && a->sign != '+')
      || (b->sign != '-' && b->sign != '+'))
    {
      /* Got to fail somehow.  Any suggestions?  */
      product->sign = 0;
      return;
    }
  product->sign = (a->sign == b->sign) ? '+' : '-';
  size_of_a = a->leader - a->low;
  size_of_b = b->leader - b->low;
  exponent = a->exponent + b->exponent;
  size_of_product = product->high - product->low;
  size_of_sum = size_of_a + size_of_b;
  extra_product_positions = size_of_product - size_of_sum;
  if (extra_product_positions < 0)
    {
      P = extra_product_positions; /* P < 0  */
      exponent -= extra_product_positions;       /* Increases exponent.  */
    }
  else
    {
      P = 0;
    }
  carry = 0;
  significant = 0;
  for (N = 0; N <= size_of_sum; N++)
    {
      work = carry;
      carry = 0;
      for (A = 0; A <= N; A++)
       {
         B = N - A;
         if (A <= size_of_a && B <= size_of_b && B >= 0)
           {
#ifdef TRACE
             printf ("a:low[%d.]=%04x b:low[%d.]=%04x work_before=%08x\n",
                    A, a->low[A], B, b->low[B], work);
#endif
             /* Watch out for sign extension!  Without the casts, on
               the DEC Alpha, the multiplication result is *signed*
               int, which gets sign-extended to convert to the
               unsigned long!  */
             work += (unsigned long) a->low[A] * (unsigned long) b->low[B];
             carry += work >> LITTLENUM_NUMBER_OF_BITS;
             work &= LITTLENUM_MASK;
#ifdef TRACE
             printf ("work=%08x carry=%04x\n", work, carry);
#endif
           }
       }
      significant |= work;
      if (significant || P < 0)
       {
         if (P >= 0)
           {
             product->low[P] = work;
#ifdef TRACE
             printf ("P=%d. work[p]:=%04x\n", P, work);
#endif
           }
         P++;
       }
      else
       {
         extra_product_positions++;
         exponent++;
       }
    }
  /* [P]-> position # size_of_sum + 1.
     This is where 'carry' should go.  */
#ifdef TRACE
  printf ("final carry =%04x\n", carry);
#endif
  if (carry)
    {
      if (extra_product_positions > 0)
       product->low[P] = carry;
      else
       {
         /* No room at high order for carry littlenum.  */
         /* Shift right 1 to make room for most significant littlenum.  */
         exponent++;
         P--;
         for (q = product->low + P; q >= product->low; q--)
           {
             work = *q;
             *q = carry;
             carry = work;
           }
       }
    }
  else
    P--;
  product->leader = product->low + P;
  product->exponent = exponent;
}

Here is the call graph for this function:

Here is the caller graph for this function: