1129210Scognet/*	$NetBSD: muldi3.c,v 1.8 2003/08/07 16:32:09 agc Exp $	*/
2129210Scognet
3129210Scognet/*-
4129210Scognet * Copyright (c) 1992, 1993
5129210Scognet *	The Regents of the University of California.  All rights reserved.
6129210Scognet *
7129210Scognet * This software was developed by the Computer Systems Engineering group
8129210Scognet * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9129210Scognet * contributed to Berkeley.
10129210Scognet *
11129210Scognet * Redistribution and use in source and binary forms, with or without
12129210Scognet * modification, are permitted provided that the following conditions
13129210Scognet * are met:
14129210Scognet * 1. Redistributions of source code must retain the above copyright
15129210Scognet *    notice, this list of conditions and the following disclaimer.
16129210Scognet * 2. Redistributions in binary form must reproduce the above copyright
17129210Scognet *    notice, this list of conditions and the following disclaimer in the
18129210Scognet *    documentation and/or other materials provided with the distribution.
19129210Scognet * 3. Neither the name of the University nor the names of its contributors
20129210Scognet *    may be used to endorse or promote products derived from this software
21129210Scognet *    without specific prior written permission.
22129210Scognet *
23129210Scognet * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24129210Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25129210Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26129210Scognet * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27129210Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28129210Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29129210Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30129210Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31129210Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32129210Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33129210Scognet * SUCH DAMAGE.
34129210Scognet */
35129210Scognet
36129210Scognet#include <sys/cdefs.h>
37129210Scognet#if defined(LIBC_SCCS) && !defined(lint)
38129210Scognet#if 0
39129210Scognetstatic char sccsid[] = "@(#)muldi3.c	8.1 (Berkeley) 6/4/93";
40129210Scognet#else
41129210Scognet__FBSDID("$FreeBSD$");
42129210Scognet#endif
43129210Scognet#endif /* LIBC_SCCS and not lint */
44129210Scognet
45129210Scognet#include <libkern/quad.h>
46129210Scognet
47129210Scognet/*
48129210Scognet * Multiply two quads.
49129210Scognet *
50129210Scognet * Our algorithm is based on the following.  Split incoming quad values
51129210Scognet * u and v (where u,v >= 0) into
52129210Scognet *
53129210Scognet *	u = 2^n u1  *  u0	(n = number of bits in `u_int', usu. 32)
54129210Scognet *
55129210Scognet * and
56129210Scognet *
57129210Scognet *	v = 2^n v1  *  v0
58129210Scognet *
59129210Scognet * Then
60129210Scognet *
61129210Scognet *	uv = 2^2n u1 v1  +  2^n u1 v0  +  2^n v1 u0  +  u0 v0
62129210Scognet *	   = 2^2n u1 v1  +     2^n (u1 v0 + v1 u0)   +  u0 v0
63129210Scognet *
64129210Scognet * Now add 2^n u1 v1 to the first term and subtract it from the middle,
65129210Scognet * and add 2^n u0 v0 to the last term and subtract it from the middle.
66129210Scognet * This gives:
67129210Scognet *
68129210Scognet *	uv = (2^2n + 2^n) (u1 v1)  +
69129210Scognet *	         (2^n)    (u1 v0 - u1 v1 + u0 v1 - u0 v0)  +
70129210Scognet *	       (2^n + 1)  (u0 v0)
71129210Scognet *
72129210Scognet * Factoring the middle a bit gives us:
73129210Scognet *
74129210Scognet *	uv = (2^2n + 2^n) (u1 v1)  +			[u1v1 = high]
75129210Scognet *		 (2^n)    (u1 - u0) (v0 - v1)  +	[(u1-u0)... = mid]
76129210Scognet *	       (2^n + 1)  (u0 v0)			[u0v0 = low]
77129210Scognet *
78129210Scognet * The terms (u1 v1), (u1 - u0) (v0 - v1), and (u0 v0) can all be done
79129210Scognet * in just half the precision of the original.  (Note that either or both
80129210Scognet * of (u1 - u0) or (v0 - v1) may be negative.)
81129210Scognet *
82129210Scognet * This algorithm is from Knuth vol. 2 (2nd ed), section 4.3.3, p. 278.
83129210Scognet *
84129210Scognet * Since C does not give us a `int * int = quad' operator, we split
85129210Scognet * our input quads into two ints, then split the two ints into two
86129210Scognet * shorts.  We can then calculate `short * short = int' in native
87129210Scognet * arithmetic.
88129210Scognet *
89129210Scognet * Our product should, strictly speaking, be a `long quad', with 128
90129210Scognet * bits, but we are going to discard the upper 64.  In other words,
91129210Scognet * we are not interested in uv, but rather in (uv mod 2^2n).  This
92129210Scognet * makes some of the terms above vanish, and we get:
93129210Scognet *
94129210Scognet *	(2^n)(high) + (2^n)(mid) + (2^n + 1)(low)
95129210Scognet *
96129210Scognet * or
97129210Scognet *
98129210Scognet *	(2^n)(high + mid + low) + low
99129210Scognet *
100129210Scognet * Furthermore, `high' and `mid' can be computed mod 2^n, as any factor
101129210Scognet * of 2^n in either one will also vanish.  Only `low' need be computed
102129210Scognet * mod 2^2n, and only because of the final term above.
103129210Scognet */
104129210Scognetstatic quad_t __lmulq(u_int, u_int);
105129210Scognet
106129210Scognetquad_t __muldi3(quad_t, quad_t);
107129210Scognetquad_t
108129210Scognet__muldi3(quad_t a, quad_t b)
109129210Scognet{
110129210Scognet	union uu u, v, low, prod;
111129210Scognet	u_int high, mid, udiff, vdiff;
112129210Scognet	int negall, negmid;
113129210Scognet#define	u1	u.ul[H]
114129210Scognet#define	u0	u.ul[L]
115129210Scognet#define	v1	v.ul[H]
116129210Scognet#define	v0	v.ul[L]
117129210Scognet
118129210Scognet	/*
119129210Scognet	 * Get u and v such that u, v >= 0.  When this is finished,
120129210Scognet	 * u1, u0, v1, and v0 will be directly accessible through the
121129210Scognet	 * int fields.
122129210Scognet	 */
123129210Scognet	if (a >= 0)
124129210Scognet		u.q = a, negall = 0;
125129210Scognet	else
126129210Scognet		u.q = -a, negall = 1;
127129210Scognet	if (b >= 0)
128129210Scognet		v.q = b;
129129210Scognet	else
130129210Scognet		v.q = -b, negall ^= 1;
131129210Scognet
132129210Scognet	if (u1 == 0 && v1 == 0) {
133129210Scognet		/*
134129210Scognet		 * An (I hope) important optimization occurs when u1 and v1
135129210Scognet		 * are both 0.  This should be common since most numbers
136129210Scognet		 * are small.  Here the product is just u0*v0.
137129210Scognet		 */
138129210Scognet		prod.q = __lmulq(u0, v0);
139129210Scognet	} else {
140129210Scognet		/*
141129210Scognet		 * Compute the three intermediate products, remembering
142129210Scognet		 * whether the middle term is negative.  We can discard
143129210Scognet		 * any upper bits in high and mid, so we can use native
144129210Scognet		 * u_int * u_int => u_int arithmetic.
145129210Scognet		 */
146129210Scognet		low.q = __lmulq(u0, v0);
147129210Scognet
148129210Scognet		if (u1 >= u0)
149129210Scognet			negmid = 0, udiff = u1 - u0;
150129210Scognet		else
151129210Scognet			negmid = 1, udiff = u0 - u1;
152129210Scognet		if (v0 >= v1)
153129210Scognet			vdiff = v0 - v1;
154129210Scognet		else
155129210Scognet			vdiff = v1 - v0, negmid ^= 1;
156129210Scognet		mid = udiff * vdiff;
157129210Scognet
158129210Scognet		high = u1 * v1;
159129210Scognet
160129210Scognet		/*
161129210Scognet		 * Assemble the final product.
162129210Scognet		 */
163129210Scognet		prod.ul[H] = high + (negmid ? -mid : mid) + low.ul[L] +
164129210Scognet		    low.ul[H];
165129210Scognet		prod.ul[L] = low.ul[L];
166129210Scognet	}
167129210Scognet	return (negall ? -prod.q : prod.q);
168129210Scognet#undef u1
169129210Scognet#undef u0
170129210Scognet#undef v1
171129210Scognet#undef v0
172129210Scognet}
173129210Scognet
174129210Scognet/*
175129210Scognet * Multiply two 2N-bit ints to produce a 4N-bit quad, where N is half
176129210Scognet * the number of bits in an int (whatever that is---the code below
177129210Scognet * does not care as long as quad.h does its part of the bargain---but
178129210Scognet * typically N==16).
179129210Scognet *
180129210Scognet * We use the same algorithm from Knuth, but this time the modulo refinement
181129210Scognet * does not apply.  On the other hand, since N is half the size of an int,
182129210Scognet * we can get away with native multiplication---none of our input terms
183129210Scognet * exceeds (UINT_MAX >> 1).
184129210Scognet *
185129210Scognet * Note that, for u_int l, the quad-precision result
186129210Scognet *
187129210Scognet *	l << N
188129210Scognet *
189129210Scognet * splits into high and low ints as HHALF(l) and LHUP(l) respectively.
190129210Scognet */
191129210Scognetstatic quad_t
192129210Scognet__lmulq(u_int u, u_int v)
193129210Scognet{
194129210Scognet	u_int u1, u0, v1, v0, udiff, vdiff, high, mid, low;
195129210Scognet	u_int prodh, prodl, was;
196129210Scognet	union uu prod;
197129210Scognet	int neg;
198129210Scognet
199129210Scognet	u1 = HHALF(u);
200129210Scognet	u0 = LHALF(u);
201129210Scognet	v1 = HHALF(v);
202129210Scognet	v0 = LHALF(v);
203129210Scognet
204129210Scognet	low = u0 * v0;
205129210Scognet
206129210Scognet	/* This is the same small-number optimization as before. */
207129210Scognet	if (u1 == 0 && v1 == 0)
208129210Scognet		return (low);
209129210Scognet
210129210Scognet	if (u1 >= u0)
211129210Scognet		udiff = u1 - u0, neg = 0;
212129210Scognet	else
213129210Scognet		udiff = u0 - u1, neg = 1;
214129210Scognet	if (v0 >= v1)
215129210Scognet		vdiff = v0 - v1;
216129210Scognet	else
217129210Scognet		vdiff = v1 - v0, neg ^= 1;
218129210Scognet	mid = udiff * vdiff;
219129210Scognet
220129210Scognet	high = u1 * v1;
221129210Scognet
222129210Scognet	/* prod = (high << 2N) + (high << N); */
223129210Scognet	prodh = high + HHALF(high);
224129210Scognet	prodl = LHUP(high);
225129210Scognet
226129210Scognet	/* if (neg) prod -= mid << N; else prod += mid << N; */
227129210Scognet	if (neg) {
228129210Scognet		was = prodl;
229129210Scognet		prodl -= LHUP(mid);
230129210Scognet		prodh -= HHALF(mid) + (prodl > was);
231129210Scognet	} else {
232129210Scognet		was = prodl;
233129210Scognet		prodl += LHUP(mid);
234129210Scognet		prodh += HHALF(mid) + (prodl < was);
235129210Scognet	}
236129210Scognet
237129210Scognet	/* prod += low << N */
238129210Scognet	was = prodl;
239129210Scognet	prodl += LHUP(low);
240129210Scognet	prodh += HHALF(low) + (prodl < was);
241129210Scognet	/* ... + low; */
242129210Scognet	if ((prodl += low) < low)
243129210Scognet		prodh++;
244129210Scognet
245129210Scognet	/* return 4N-bit product */
246129210Scognet	prod.ul[H] = prodh;
247129210Scognet	prod.ul[L] = prodl;
248129210Scognet	return (prod.q);
249129210Scognet}
250