/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:mulu211.c 12.0$ */
/* $ACIS:mulu211.c 12.0$ */
/* $Source: /ibm/acis/usr/src/lib/libc/ca/gen/RCS/mulu211.c,v $ */

#ifndef lint
static char *rcsid = "$Header:mulu211.c 12.0$";
#endif

/* MULTIPLY TWO LONGWORDS, GIVING TWO-LONGWORD PRODUCT

The arguments are two unsigned longword integers. The result is 
the two-longword product of the arguments.

The algorithm treats the arguments as vectors of two shortwords 
each. These are multiplied in the required combinations to give 
longword results, which are in turn treated as two shortwords 
each. These are aligned and added appropriately to give the 
desired result. The products and their alignments can be pictured 
as follows:

            p |b[0]|b[1]|   =    p.a
       q |b[0]|b[1]|        =   q.a 
       r |b[0]|b[1]|        =   r.a 
                          
       s |b[0]|b[1]|        =   s.a 
                          
  n |   [0]   |   [1]   |              

Many 32-bit computers provide an instruction which accomplishes 
this function directly, and for such computers (those based on 
the Motorola 68020, for example) the direct facility should be 
used rather than this function. */ 

#define U unsigned long 
#define S unsigned short

union t {U a; S b[2];};

void _mulu211 (c, d, n)
union t c, d;
U n[];

{union t p, q, r, s;

 p.a = (U)c.b[1] * (U)d.b[1];
 q.a = (U)c.b[0] * (U)d.b[1];
 r.a = (U)c.b[1] * (U)d.b[0];
 s.a = (U)p.b[0] + (U)q.b[1] + (U)r.b[1];

 n[0] = (U)q.b[0] + (U)r.b[0] + (U)s.b[0] + (U)c.b[0] * (U)d.b[0];
 n[1] = (U)p.b[1] | (U)s.b[1] << 16; }

/* Test program for _mulu211 */
/* Remove the comment start/stop groups around this next sequence 
to obtain main function for testing  _mulu211.

main ()
{unsigned long a, b, c[2];

 for (;;) {printf("? ");
           scanf("%lx %lx", &a, &b);
           printf("a:%08lx  b:%08lx\n", a, b);
           _mulu211(a, b, c);
           printf("c: %08lx %08lx\n", c[0], c[1]);}}*/
