Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
cray_fadd.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 /*
00037  *      Portable Cray floating-point addition/subtraction emulation
00038  */
00039 
00040 #include "arith.internal.h"
00041 
00042 
00043 int
00044 ar_cfadd64 (AR_CRAY_64 *x,
00045             const AR_CRAY_64 *a,
00046             const AR_CRAY_64 *b) {
00047 
00048         int res = AR_STAT_OK, a_expo = a->expo, b_expo = b->expo;
00049         unsigned int carry, shift, inexact;
00050         AR_CRAY_64 y;
00051 
00052         /* Ensure that the first argument has the largest exponent */
00053         if (b_expo > a_expo)
00054                 y = *a, *x = *b;
00055         else
00056                 y = *b, *x = *a;
00057 
00058         /* Test for underflow */
00059         if (x->expo < AR_CRAY_MIN_EXPO) {
00060                 ZEROCRAY64 (*x);
00061                 return AR_STAT_UNDERFLOW | AR_STAT_ZERO;
00062         }
00063 
00064         /* Shift the coefficient of the second argument down (right). We
00065          * do this in parts so as not to overflow registers.
00066          */
00067         inexact = 0;
00068         shift = x->expo - y.expo;
00069         if (shift > AR_CRAY64_COEFF_BITS)
00070                 ZEROCRAY64 (y);
00071         else {
00072                 for (; shift; shift--) {
00073                         inexact |= y.coeff2 & 1;
00074                         SHRIGHTCRAY64 (y);
00075                         y.expo++;
00076                 }
00077         }
00078 
00079         /* If signs differ, complement the first argument; this is equivalent
00080          * to negating and then subtracting one, in a two's complement sense.
00081          */
00082         if (x->sign != y.sign)
00083                 NOTCRAY64 (*x);
00084 
00085         /* Compute sum of coefficients */
00086         carry = 0;
00087         ADDCRAY64 (*x, carry, *x, y);
00088 
00089         /* Check if the sign changed, and add 1 if so; otherwise, undo
00090          * the complement.
00091          */
00092         if (x->sign != y.sign)
00093                 if (carry) {
00094                         x->sign ^= 1;
00095                         carry = 1;
00096                         INCCRAY64 (*x, carry);
00097                         carry = 0;
00098                 } else
00099                         NOTCRAY64 (*x);
00100 
00101         if (carry) {
00102                 SHRIGHTCRAY64 (*x);
00103                 x->coeff0 |= 1 << (AR_CRAY_C0_BITS - 1);
00104                 x->expo++;
00105         }
00106 
00107         /* Check for a zero result, as a special case */
00108         if (!(x->coeff0 | x->coeff1 | x->coeff2)) {
00109                 x->sign = x->expo = 0;
00110                 return AR_STAT_ZERO;
00111         }
00112 
00113         /* Shift the result coefficient left until normalized */
00114         while (!(x->coeff0 >> (AR_CRAY_C0_BITS - 1))) {
00115                 x->expo--;
00116                 SHLEFTCRAY64 (*x);
00117         }
00118 
00119         /* Test for out-of-range result or operand */
00120         if (x->expo > AR_CRAY_MAX_EXPO ||
00121             a_expo > AR_CRAY_MAX_EXPO ||
00122             b_expo > AR_CRAY_MAX_EXPO) {
00123                 x->sign = 0;
00124                 x->expo = AR_CRAY_MAX_EXPO + 1;
00125                 res |= AR_STAT_OVERFLOW;
00126         }
00127 
00128         if (inexact)
00129                 res |= AR_STAT_INEXACT;
00130         if (x->sign)
00131                 res |= AR_STAT_NEGATIVE;
00132 
00133         return res;
00134 }
00135 
00136 
00137 int
00138 ar_cfsub64 (AR_CRAY_64 *x,
00139             const AR_CRAY_64 *a,
00140             const AR_CRAY_64 *b) {
00141 
00142         AR_CRAY_64 nb = *b;
00143 
00144         nb.sign ^= 1;
00145         return ar_cfadd64 (x, a, &nb);
00146 }
00147 
00148 
00149 int
00150 ar_cfadd128 (AR_CRAY_128 *x,
00151              const AR_CRAY_128 *a,
00152              const AR_CRAY_128 *b) {
00153 
00154         int res = AR_STAT_OK, x_expo;
00155         long carry, shift, inexact;
00156         AR_CRAY_128 y;
00157 
00158         x->zero = 0;
00159 
00160         /* Ensure that the first argument has the largest absolute value
00161          * (assuming normalized inputs)
00162          */
00163         if (b->expo > a->expo ||
00164             b->expo == a->expo &&
00165             (b->coeff0 > a->coeff0 ||
00166              b->coeff0 == a->coeff0 &&
00167              (b->coeff1 > a->coeff1 ||
00168               b->coeff1 == a->coeff1 &&
00169               (b->coeff2 > a->coeff2 ||
00170                b->coeff2 == a->coeff2 &&
00171                (b->coeff3 > a->coeff3 ||
00172                 b->coeff3 == a->coeff3 &&
00173                 (b->coeff4 > a->coeff4 ||
00174                  b->coeff4 == a->coeff4 &&
00175                  b->coeff5 > a->coeff5))))))
00176                 y = *a, *x = *b;
00177         else
00178                 y = *b, *x = *a;
00179 
00180         if ((x_expo = x->expo) > AR_CRAY_MAX_EXPO) {
00181                 ZEROCRAY128 (*x);
00182                 x->expo = AR_CRAY_MAX_EXPO + 1;
00183                 x->coeff0 = 1 << (AR_CRAY_C0_BITS - 1);
00184                 return AR_STAT_OVERFLOW;
00185         }
00186 
00187         /* Shift the coefficient of the second argument down (right) */
00188         inexact = 0;
00189         shift = x_expo - y.expo;
00190         if (shift > AR_CRAY128_COEFF_BITS)
00191                 ZEROCRAY128 (y);
00192         else
00193                 for (; shift; shift--) {
00194                         inexact |= y.coeff5 & 1;
00195                         SHRIGHTCRAY128 (y);
00196                         y.expo++;
00197                 }
00198 
00199         /* If signs differ, negate the second argument in two's complement. */
00200         if (x->sign != y.sign) {
00201                 NOTCRAY128 (y);
00202                 carry = 1;
00203         } else
00204                 carry = 0;
00205 
00206         /* Compute sum of coefficients */
00207         ADDCRAY128 (*x, carry, *x, y);
00208 
00209         /* Handle a carry out of the upper bit */
00210         if (x->sign != y.sign)
00211                 carry--;
00212 
00213         if (carry < 0) {
00214 
00215                 /* Bug reproduction from a negative shift count resulting
00216                  * from an unnormalized argument in a subtraction.
00217                  */
00218                 x_expo += 16;
00219                 x->coeff0 = x->coeff1 = x->coeff2 =
00220                         x->coeff3 = x->coeff4 = x->coeff5 = 0;
00221 
00222         } else if (carry > 0) {
00223 
00224                 /* Handle carry out of coefficient */
00225                 if (carry > 0) {
00226                         SHRIGHTCRAY128 (*x);
00227                         x->coeff0 |= 1 << (AR_CRAY_C0_BITS - 1);
00228                         x_expo++;
00229                 }
00230 
00231         } else if (x->coeff0 | x->coeff1 | x->coeff2 |
00232                    x->coeff3 | x->coeff4 | x->coeff5) {
00233 
00234                 /* Shift the nonzero result coefficient left until normalized */
00235                 while (!(x->coeff0 >> (AR_CRAY_C0_BITS - 1))) {
00236                         x_expo--;
00237                         SHLEFTCRAY128 (*x);
00238                 }
00239 
00240         } else if (x_expo >= AR_CRAY_MIN_EXPO && x_expo <= AR_CRAY_MAX_EXPO) {
00241 
00242                 /* Zero result */
00243                 x->sign = 0;
00244                 x_expo = 0;
00245                 res |= AR_STAT_ZERO;
00246         }
00247 
00248         /* Test for out-of-range result or operand, as well as an
00249          * underflowed result.
00250          */
00251         if (x_expo > AR_CRAY_MAX_EXPO) {
00252                 ZEROCRAY128 (*x);
00253                 x->expo = AR_CRAY_MAX_EXPO + 1;
00254                 x->coeff0 = 1 << (AR_CRAY_C0_BITS - 1);
00255                 res |= AR_STAT_OVERFLOW;
00256         } else if (x_expo < AR_CRAY_MIN_EXPO) {
00257                 ZEROCRAY128 (*x);
00258                 res |= AR_STAT_UNDERFLOW | AR_STAT_ZERO;
00259         } else
00260                 x->expo = x_expo;
00261 
00262         if (inexact)
00263                 res |= AR_STAT_INEXACT;
00264         if (x->sign)
00265                 res |= AR_STAT_NEGATIVE;
00266 
00267         return res;
00268 }
00269 
00270 
00271 int
00272 ar_cfsub128 (AR_CRAY_128 *x,
00273              const AR_CRAY_128 *a,
00274              const AR_CRAY_128 *b) {
00275 
00276         AR_CRAY_128 nb = *b;
00277 
00278         nb.sign ^= 1;
00279         return ar_cfadd128 (x, a, &nb);
00280 }
00281 
00282 
00283 static char USMID [] = "\n%Z%%M%        %I%     %G% %U%\n";
00284 static char rcsid [] = "$Id: cray_fadd.c,v 1.1.1.1 2002-05-22 20:06:18 dsystem Exp $";
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines