Annotation of embedaddon/ntp/libparse/mfp_mul.c, revision 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>