Listing 4: Function GetMachar extracts floating
point characteristics

  1: /* ============ */
  2: /* getmachx.h    */
  3: /* ============ */
  4: # if defined(__GETMACHX_H__)
  5: #    /* Do Nothing */
  6: # else
  7: #    define    __GETMACHX_H__
  8: #include <stdio.h>
  9: #include <stdlib.h>
 10: //#include <math.h>
 11: #include <float.h>
 12: #include "machars.h"
 13: /* Get machine characteristics - after Plauger's elefunt */
 14: /* ===================================================== */
 15: /* GetMachar - Determines Computer's Floating-Point      */
 15: /* Characteristics                                       */
 16: /* ===================================================== */
 17: MACHAR_STRU
 18: GetMachar(void)
 19: {
 20:     short        k, n;
 21:     const
 22:     TYPE     Zero = 0, One = 1;
 23:     TYPE         T0, T1, T2;
 24:     MACHAR_STRU  MachData;
 25:
 26:     /* --------------- */
 27:     /* Determine Radix */
 28:     /* --------------- */
 29:
 30:     MachData.Radix = FLT_RADIX;
 31:
 32:     /* -------------------------------- */
 33:     /* Determine No. Digits in Fraction */
 34:     /* -------------------------------- */
 35: #   if defined(FLT)
 36:     MachData.FracDigs = FLT_MANT_DIG;
 37: #   elif defined(DBL)
 38:     MachData.FracDigs = DBL_MANT_DIG;
 39: #   else
 40:     MachData.FracDigs = LDBL_MANT_DIG;
 41: #   endif
 42:
 43:     /* -------------------------------- */
 44:     /* Determine Whether Floating Point */
 45:     /* Addition Chops (0) or Rounds (1) */
 46:     /* -------------------------------- */
 47: #   if defined(FLT)
 48:     MachData.Rounds = FLT_ROUNDS;
 49: #   elif defined(DBL)
 50:     MachData.Rounds = DBL_ROUNDS;
 51: #   else
 52:     MachData.Rounds = LDBL_ROUNDS;
 53: #   endif
 54:
 55:     /* ---------------- */
 56:     /* Determine EpsNeg */
 57:     /* ---------------- */
 58:
 59:     T0 = (TYPE)1 / (TYPE)MachData.Radix;
 60:
 61:     for (T1 = 1 - T0; T1 < (TYPE)1; T0 /= MachData.Radix)
 62:     {
 63:     T1 = (TYPE)1 - T0;
 64:     }
 65:
 66:     /* ---------------------- */
 67:     /* Difference between 1.0 */
 68:     /* & minimum number < 1.0 */
 69:     /* ---------------------- */
 70:     T2 = T0 * MachData.Radix;
 71:     MachData.EpsNeg = T2;
 72:
 73:     /* -------------------------------------- */
 74:     /* Correct EpsNeg for Non-Binary Machines */
 75:     /* -------------------------------------- */
 76:     if (MachData.Radix != 2 && MachData.Rounds != 0)
 77:     {
 78:     T0 = T2 * (One + T2) / (One + One);
 79:     T0 = One - T0;
 80:     if (T0 - One != 0)
 81:         MachData.EpsNeg = T0;
 82:     }
 83:
 84:     /* ------------- */
 85:     /* Determine Eps */
 86:     /* ------------- */
 87:     T0 = One / (TYPE) MachData.Radix;
 88:
 89:     for (T1 = 1 + T0; T1 > 1; T0 /= MachData.Radix)
 90:     {
 91:     T1 = 1 + T0;
 92:     }
 93:
 94:     /* ---------------------- */
 95:     /* Difference between 1.0 */
 96:     /* & minimum number > 1.0 */
 97:     /* ---------------------- */
 98:     T2 = T0 * MachData.Radix;
 99:     MachData.Eps = T2;
100:
101:     /* ----------------------------------- */
102:     /* Correct Eps for Non-Binary Machines */
103:     /* ----------------------------------- */
104:     if (MachData.Radix != 2 && MachData.Rounds != 0)
105:     {
106:     T0 = T2 * (One + T2) / (One + One);
107:     T0 = One + T0;
108:     if (T0 - One != 0)
109:         MachData.Eps = T0;
110:     }
111:
112:     /* -------------------------- */
113:     /* Determine Number of Guard  */
114:     /* Digits Used Multiplication */
115:     /* -------------------------- */
116:     MachData.NumGuard = 0;
117:     if (MachData.Rounds == 0 &&
118:     (One + MachData.Eps) * One - One != Zero)
119:     MachData.NumGuard = 1;
120:
121:     /* --------------------------------------------- */
122:     /* Determine ExpDigits, MaxExp, MinExp, Max, Min */
123:     /* --------------------------------------------- */
124:     T1 = One / (TYPE) MachData.Radix;
125:
126:     /* ------------------------ */
127:     /* Count Digits in Exponent */
128:     /* ------------------------ */
129:     for (k = 0, n = 1;; ++k, n += n)
130:     {
131:     T2 = T1;
132:     T1 *= T1;
133:     T0 = T1 * One;
134:     if (T0 + T0 == Zero || T2 <= (T1 < 0 ? -T1 : T1))
135:         break;
136:     }
137:     if (MachData.Radix != 10)
138:     MachData.ExpDigits = (short)(k + 1);
139:     else
140:     for (MachData.ExpDigits = 2,k = MachData.Radix; k <= n;)
141:         ++MachData.ExpDigits, k *= MachData.Radix;
142:
143:     /* ---------------- */
144:     /* Maximum Exponent */
145:     /* ---------------- */
146: #   if defined(FLT)
147:     MachData.MaxExp = FLT_MAX_EXP;
148: #   elif defined(DBL)
149:     MachData.MaxExp = DBL_MAX_EXP;
150: #   else
151:     MachData.MaxExp = LDBL_MAX_EXP;
152: #   endif
153: # if 0
154:     if (T0 != T1)
155:     MachData.MaxExp -= 2;
156: # endif
157:
158:     /* ----------------------------- */
159:     /* Maximum Floating Point Number */
160:     /* ----------------------------- */
161: #   if defined(FLT)
162:     MachData.Max = FLT_MAX;
163: #   elif defined(DBL)
164:     MachData.Max = DBL_MAX;
165: #   else
166:     MachData.Max = LDBL_MAX;
167: #   endif
168:
169:     /* ----------------------------- */
170:     /* Minimum Floating Point Number */
171:     /* ----------------------------- */
172: #   if defined(FLT)
173:     MachData.Min = FLT_MIN;
174: #   elif defined(DBL)
175:     MachData.Min = DBL_MIN;
176: #   else
177:     MachData.Min = LDBL_MIN;
178: #   endif
179:
180:     /* ---------------- */
181:     /* Minimum Exponent */
182:     /* ---------------- */
183: #   if defined(FLT)
184:     MachData.MinExp = FLT_MIN_EXP;
185: #   elif defined(DBL)
186:     MachData.MinExp = DBL_MIN_EXP;
187: #   else
188:     MachData.MinExp = LDBL_MIN_EXP;
189: #   endif
190:
191:     return MachData;
192: }
193: # if defined(TEST_MACHX)
194: void
195: main()
196: {
197:     MACHAR_STRU MachData;
198:
199:     MachData = GetMachar();
200:
201:     printf("Radix                  = %d\n"
202:        "Fraction Digits        = %d\n"
203:        "No. Mult. Guard Digits = %d\n",
204:     MachData.Radix,
205:     MachData.FracDigs,
206:     MachData.NumGuard);
207:     printf("ExpDigits              = %d\n"
208:            "MaxExp                 = %d\n"
209:        "MinExp                 = %d\n",
210:        MachData.ExpDigits,
211:        MachData.MaxExp,
212:        MachData.MinExp);
213:     printf("\nFloating Point Addition %ss\n\n",
214:     (MachData.Rounds) ? "Round" : "Chop");
215:     printf("Eps                 = %.10LG\n",
216:     (long double)MachData.Eps);
217:     printf("EpsNeg              = %.10LG\n",
218:     (long double)MachData.EpsNeg);
219:     printf("Max (Largest F.P.)  = %.10LG\n"
220:            "Min (Smallest F.P.) = %.10LG\n",
221:        (long double)MachData.Max,
222:        (long double)MachData.Min);
223: }
224: # endif            /* TEST */
225: # endif            /* __GETMACHX_H__ */

/* End of File */