Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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.1 of the GNU Lesser General Public License 00007 as 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 Lesser General Public 00021 License along with this program; if not, write the Free Software 00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 00023 USA. 00024 00025 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00026 Mountain View, CA 94043, or: 00027 00028 http://www.sgi.com 00029 00030 For further information regarding this notice, see: 00031 00032 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00033 00034 */ 00035 00036 00037 #pragma ident "@(#) libfi/element/modulo.c 92.2 06/16/99 15:47:23" 00038 00039 #include <fortran.h> 00040 /* keep the order of math.h and fp.h for huge_val */ 00041 #include <math.h> 00042 #if !defined(__mips) && !defined(_LITTLE_ENDIAN) 00043 #define _HALF_NaN 0x7fc000 00044 #define _SGL_NaN 0x7ff8000000000000LL 00045 #define _DBL_NaN 0x0000000000000000LL 00046 #endif /* NOT __mips and NOT _LITTLE_ENDIAN, assume sparc */ 00047 #include <stddef.h> 00048 #include <cray/portdefs.h> 00049 00050 #if !defined(__mips) && !defined(_LITTLE_ENDIAN) 00051 #ifdef _WORD32 00052 #if _F_REAL16 == 1 00053 #define floorl __floorl 00054 _f_real16 __floorl(_f_real16 x); 00055 extern long double __floorl(); 00056 #endif /* END _REAL16 == 1 */ 00057 #endif /* END _WORD32 */ 00058 #endif /* END NOT __mips and NOT _LITTLE_ENDIAN */ 00059 00060 /* 00061 * _MODULO_X(A,P) - called by compiled Fortran programs to calculate 00062 * the modulo of type integer or real arguments. 00063 * 00064 * where X is: 00065 * I4 for 32-bit integer 00066 * I for 46-bit integer 00067 * J for 64-bit integer 00068 * S4 for 32-bit real 00069 * S for 64-bit real 00070 * D for 128-bit real 00071 * 00072 * The standard definition for integer is: 00073 * If p != 0, modulo(a,p) = r, where A = q * p + r, 00074 * q is an integer, 00075 * 0 <= r < p if p > 0 00076 * p < r <= 0 if p < 0 00077 * if p = 0, the result is processor dependent 00078 * The standard definition for real is: 00079 * If p != 0, modulo(a,p) = A - FLOOR(a/p) * p 00080 * if p = 0, the result is processor dependent 00081 * 00082 * The algorithm for integer is: 00083 * If A and P have the same sign, use: 00084 * (a - INT(a/p) * p), 00085 * 00086 * else when A and P have different signs, 00087 * if a/p has a zero remainder, use: 00088 * a - INT(a/p) * p, 00089 * 00090 * else a/p has a nonzero remainder, use: 00091 * a - (INT(a/p) - 1) * p. 00092 * 00093 * The algorithm for real is: 00094 * a - FLOOR(a/p) * p. 00095 * For non-IEEE systems, check size of result 00096 */ 00097 00098 #ifdef _F_INT4 00099 _f_int4 00100 _MODULO_I4 (_f_int4 *arga, _f_int4 *argp) 00101 { 00102 _f_int4 parg; 00103 _f_int4 aarg; 00104 _f_int4 res; 00105 _f_int4 inter; 00106 _f_int4 corectn; 00107 parg = *argp; 00108 aarg = *arga; 00109 00110 /* prevent divide by zero */ 00111 if (parg == 0) 00112 return(0); 00113 inter = aarg/parg; 00114 res = aarg - inter * parg; 00115 corectn = (parg > 0) ? ((res >= 0) ? 0 : parg) : 00116 ((res <= 0) ? 0 : parg); 00117 res = res + corectn; 00118 return(res); 00119 } 00120 #endif /* _F_INT4 */ 00121 00122 00123 #ifdef _F_INT6 00124 _f_int6 00125 _MODULO_I (_f_int6 *arga, _f_int6 *argp) 00126 { 00127 _f_int6 parg; 00128 _f_int6 aarg; 00129 _f_int6 res; 00130 _f_int6 inter; 00131 _f_int6 corectn; 00132 parg = *argp; 00133 aarg = *arga; 00134 00135 /* prevent divide by zero */ 00136 if (parg == 0) 00137 return(0); 00138 inter = aarg/parg; 00139 res = aarg - inter * parg; 00140 corectn = (parg > 0) ? ((res >= 0) ? 0 : parg) : 00141 ((res <= 0) ? 0 : parg); 00142 res = res + corectn; 00143 return(res); 00144 } 00145 #endif /* _F_INT6 */ 00146 00147 00148 #ifdef _F_INT8 00149 _f_int8 00150 _MODULO_J (_f_int8 *arga, _f_int8 *argp) 00151 { 00152 _f_int8 parg; 00153 _f_int8 aarg; 00154 _f_int8 res; 00155 _f_int8 inter; 00156 _f_int8 corectn; 00157 parg = *argp; 00158 aarg = *arga; 00159 00160 /* prevent divide by zero */ 00161 if (parg == 0) 00162 return(0); 00163 inter = aarg/parg; 00164 res = aarg - inter * parg; 00165 corectn = (parg > 0) ? ((res >= 0) ? 0 : parg) : 00166 ((res <= 0) ? 0 : parg); 00167 res = res + corectn; 00168 return(res); 00169 } 00170 #endif /* _F_INT8 */ 00171 00172 00173 #ifdef _F_REAL4 00174 _f_real4 00175 #if defined(__mips) || defined(_LITTLE_ENDIAN) 00176 _modulo4 (_f_real4 arga, _f_real4 argp) 00177 { 00178 #if defined(__mips) 00179 return (arga - (floorf(arga/argp)) * argp); 00180 #else /* ELSE of __mips is LITTLE_ENDIAN. */ 00181 _f_real4 __floorf(_f_real4 arg); 00182 return (arga - (__floorf(arga/argp)) * argp); 00183 #endif /* ENDIF of __mips */ 00184 } 00185 #else /* __mips or _LITTLE_ENDIAN */ 00186 _MODULO_S4 (_f_real4 *arga, _f_real4 *argp) 00187 { 00188 _f_real4 aarg; 00189 _f_real4 parg; 00190 _f_real4 res; 00191 parg = *argp; 00192 aarg = *arga; 00193 if (parg == 0) 00194 #ifdef IEEE_FLOATING_POINT 00195 return(_HALF_NaN); 00196 #else 00197 return(0); 00198 #endif 00199 res = aarg - (floor((_f_real8)(aarg/parg)) * parg); 00200 #ifndef IEEE_FLOATING_POINT 00201 if (fabs((_f_real8)res) >= fabs((_f_real8)parg)) 00202 res -= parg; 00203 #endif 00204 return(res); 00205 } 00206 #endif /* __mips or _LITTLE_ENDIAN */ 00207 #endif /* _F_REAL4 */ 00208 00209 00210 #ifdef _F_REAL8 00211 _f_real8 00212 #if defined(__mips) || defined(_LITTLE_ENDIAN) 00213 _modulo8 (_f_real8 arga, _f_real8 argp) 00214 { 00215 #if defined(__mips) 00216 return (arga - (floor(arga/argp)) * argp); 00217 #else /* ELSE of __mips is LITTLE_ENDIAN. */ 00218 return (arga - (__floor(arga/argp)) * argp); 00219 #endif /* ENDIF of __mips */ 00220 } 00221 #else /* __mips or _LITTLE_ENDIAN */ 00222 _MODULO_S (_f_real8 *arga, _f_real8 *argp) 00223 { 00224 _f_real8 aarg; 00225 _f_real8 parg; 00226 _f_real8 res; 00227 parg = *argp; 00228 aarg = *arga; 00229 if (parg == 0) 00230 #ifdef IEEE_FLOATING_POINT 00231 return(_SGL_NaN); 00232 #else 00233 return((_f_real8) 0); 00234 #endif 00235 res = aarg - (floor((_f_real8)(aarg/parg)) * parg); 00236 #ifndef IEEE_FLOATING_POINT 00237 if (fabs((_f_real8)res) >= fabs((_f_real8)parg)) 00238 res -= parg; 00239 #endif 00240 return(res); 00241 } 00242 #endif /* __mips or _LITTLE_ENDIAN */ 00243 #endif /* _F_REAL8 */ 00244 00245 00246 #if _F_REAL16 == 1 00247 _f_real16 00248 #if defined(__mips) || defined(_LITTLE_ENDIAN) 00249 _moduloq (_f_real16 arga, _f_real16 argp) 00250 { 00251 #if defined(__mips) 00252 return (arga - (floorl(arga/argp)) * argp); 00253 #else /* ELSE of __mips is LITTLE_ENDIAN. */ 00254 _f_real16 __floorl(_f_real16 arg); 00255 return (arga - (__floorl(arga/argp)) * argp); 00256 #endif /* ENDIF of __mips */ 00257 } 00258 #else /* __mips or _LITTLE_ENDIAN */ 00259 _MODULO_D (_f_real16 *arga, _f_real16 *argp) 00260 { 00261 _f_real16 aarg; 00262 _f_real16 parg; 00263 _f_real16 res; 00264 parg = *argp; 00265 aarg = *arga; 00266 if (parg == 0) 00267 #ifdef IEEE_FLOATING_POINT 00268 return(_DBL_NaN); 00269 #else 00270 return((_f_real16) 0); 00271 #endif /* IEEE_FLOATING_POINT */ 00272 00273 res = aarg - (floorl((_f_real16)(aarg/parg)) * parg); 00274 00275 #ifndef IEEE_FLOATING_POINT 00276 if (fabsl((_f_real16)res) >= fabsl((_f_real16)parg)) 00277 res -= parg; 00278 #endif /* not IEEE_FLOATING_POINT */ 00279 return(res); 00280 } 00281 #endif /* __mips or _LITTLE_ENDIAN */ 00282 #endif /* end of 128-bit float modulo */