Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
modulo.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.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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines