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 */