Annotation of embedaddon/ntp/libparse/mfp_mul.c, revision 1.1.1.1
1.1 misho 1: /*
2: * /src/NTP/ntp4-dev/libparse/mfp_mul.c,v 4.9 2005/07/17 20:34:40 kardel RELEASE_20050717_A
3: *
4: * mfp_mul.c,v 4.9 2005/07/17 20:34:40 kardel RELEASE_20050717_A
5: *
6: * $Created: Sat Aug 16 20:35:08 1997 $
7: *
8: * Copyright (c) 1997-2005 by Frank Kardel <kardel <AT> ntp.org>
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the author nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: */
35: #include <stdio.h>
36: #include "ntp_stdlib.h"
37: #include "ntp_types.h"
38: #include "ntp_fp.h"
39:
40: #define LOW_MASK (u_int32)((1<<(FRACTION_PREC/2))-1)
41: #define HIGH_MASK (u_int32)(LOW_MASK << (FRACTION_PREC/2))
42:
43: /*
44: * for those who worry about overflows (possibly triggered by static analysis tools):
45: *
46: * Largest value of a 2^n bit number is 2^n-1.
47: * Thus the result is: (2^n-1)*(2^n-1) = 2^2n - 2^n - 2^n + 1 < 2^2n
48: * Here overflow can not happen for 2 reasons:
49: * 1) the code actually multiplies the absolute values of two signed
50: * 64bit quantities.thus effectively multiplying 2 63bit quantities.
51: * 2) Carry propagation is from low to high, building principle is
52: * addition, so no storage for the 2^2n term from above is needed.
53: */
54:
55: void
56: mfp_mul(
57: int32 *o_i,
58: u_int32 *o_f,
59: int32 a_i,
60: u_int32 a_f,
61: int32 b_i,
62: u_int32 b_f
63: )
64: {
65: int32 i, j;
66: u_int32 f;
67: u_long a[4]; /* operand a */
68: u_long b[4]; /* operand b */
69: u_long c[5]; /* result c - 5 items for performance - see below */
70: u_long carry;
71:
72: int neg = 0;
73:
74: if (a_i < 0) /* examine sign situation */
75: {
76: neg = 1;
77: M_NEG(a_i, a_f);
78: }
79:
80: if (b_i < 0) /* examine sign situation */
81: {
82: neg = !neg;
83: M_NEG(b_i, b_f);
84: }
85:
86: a[0] = a_f & LOW_MASK; /* prepare a operand */
87: a[1] = (a_f & HIGH_MASK) >> (FRACTION_PREC/2);
88: a[2] = a_i & LOW_MASK;
89: a[3] = (a_i & HIGH_MASK) >> (FRACTION_PREC/2);
90:
91: b[0] = b_f & LOW_MASK; /* prepare b operand */
92: b[1] = (b_f & HIGH_MASK) >> (FRACTION_PREC/2);
93: b[2] = b_i & LOW_MASK;
94: b[3] = (b_i & HIGH_MASK) >> (FRACTION_PREC/2);
95:
96: c[0] = c[1] = c[2] = c[3] = c[4] = 0;
97:
98: for (i = 0; i < 4; i++) /* we do assume 32 * 32 = 64 bit multiplication */
99: for (j = 0; j < 4; j++)
100: {
101: u_long result_low, result_high;
102: int low_index = (i+j)/2; /* formal [0..3] - index for low long word */
103: int mid_index = 1+low_index; /* formal [1..4]! - index for high long word
104: will generate unecessary add of 0 to c[4]
105: but save 15 'if (result_high) expressions' */
106: int high_index = 1+mid_index; /* formal [2..5]! - index for high word overflow
107: - only assigned on overflow (limits range to 2..3) */
108:
109: result_low = (u_long)a[i] * (u_long)b[j]; /* partial product */
110:
111: if ((i+j) & 1) /* splits across two result registers */
112: {
113: result_high = result_low >> (FRACTION_PREC/2);
114: result_low <<= FRACTION_PREC/2;
115: carry = (unsigned)1<<(FRACTION_PREC/2);
116: }
117: else
118: { /* stays in a result register - except for overflows */
119: result_high = 0;
120: carry = 1;
121: }
122:
123: if (((c[low_index] >> 1) + (result_low >> 1) + ((c[low_index] & result_low & carry) != 0)) &
124: (u_int32)((unsigned)1<<(FRACTION_PREC - 1))) {
125: result_high++; /* propagate overflows */
126: }
127:
128: c[low_index] += result_low; /* add up partial products */
129:
130: if (((c[mid_index] >> 1) + (result_high >> 1) + ((c[mid_index] & result_high & 1) != 0)) &
131: (u_int32)((unsigned)1<<(FRACTION_PREC - 1))) {
132: c[high_index]++; /* propagate overflows of high word sum */
133: }
134:
135: c[mid_index] += result_high; /* will add a 0 to c[4] once but saves 15 if conditions */
136: }
137:
138: #ifdef DEBUG
139: if (debug > 6)
140: printf("mfp_mul: 0x%04lx%04lx%04lx%04lx * 0x%04lx%04lx%04lx%04lx = 0x%08lx%08lx%08lx%08lx\n",
141: a[3], a[2], a[1], a[0], b[3], b[2], b[1], b[0], c[3], c[2], c[1], c[0]);
142: #endif
143:
144: if (c[3]) /* overflow */
145: {
146: i = ((unsigned)1 << (FRACTION_PREC-1)) - 1;
147: f = ~(unsigned)0;
148: }
149: else
150: { /* take produkt - discarding extra precision */
151: i = c[2];
152: f = c[1];
153: }
154:
155: if (neg) /* recover sign */
156: {
157: M_NEG(i, f);
158: }
159:
160: *o_i = i;
161: *o_f = f;
162:
163: #ifdef DEBUG
164: if (debug > 6)
165: printf("mfp_mul: %s * %s => %s\n",
166: mfptoa((u_long)a_i, a_f, 6),
167: mfptoa((u_long)b_i, b_f, 6),
168: mfptoa((u_long)i, f, 6));
169: #endif
170: }
171:
172: /*
173: * History:
174: *
175: * mfp_mul.c,v
176: * Revision 4.9 2005/07/17 20:34:40 kardel
177: * correct carry propagation implementation
178: *
179: * Revision 4.8 2005/07/12 16:17:26 kardel
180: * add explanation why we do not write into c[4]
181: *
182: * Revision 4.7 2005/04/16 17:32:10 kardel
183: * update copyright
184: *
185: * Revision 4.6 2004/11/14 15:29:41 kardel
186: * support PPSAPI, upgrade Copyright to Berkeley style
187: *
188: * Revision 4.3 1999/02/21 12:17:37 kardel
189: * 4.91f reconcilation
190: *
191: * Revision 4.2 1998/12/20 23:45:28 kardel
192: * fix types and warnings
193: *
194: * Revision 4.1 1998/05/24 07:59:57 kardel
195: * conditional debug support
196: *
197: * Revision 4.0 1998/04/10 19:46:38 kardel
198: * Start 4.0 release version numbering
199: *
200: * Revision 1.1 1998/04/10 19:27:47 kardel
201: * initial NTP VERSION 4 integration of PARSE with GPS166 binary support
202: *
203: * Revision 1.1 1997/10/06 21:05:46 kardel
204: * new parse structure
205: *
206: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>