|
|
1.1 root 1: #! /bin/sh
2:
3: # $Id: ieee754-misc-auto.sh,v 1.2 2005/05/11 00:13:33 fredette Exp $
4:
5: # ic/ieee754/ieee754-misc-auto.sh - automatically generates C code
6: # for miscellaneous IEEE 754 emulation support:
7:
8: #
9: # Copyright (c) 2004 Matt Fredette
10: # All rights reserved.
11: #
12: # Redistribution and use in source and binary forms, with or without
13: # modification, are permitted provided that the following conditions
14: # are met:
15: # 1. Redistributions of source code must retain the above copyright
16: # notice, this list of conditions and the following disclaimer.
17: # 2. Redistributions in binary form must reproduce the above copyright
18: # notice, this list of conditions and the following disclaimer in the
19: # documentation and/or other materials provided with the distribution.
20: # 3. All advertising materials mentioning features or use of this software
21: # must display the following acknowledgement:
22: # This product includes software developed by Matt Fredette.
23: # 4. The name of the author may not be used to endorse or promote products
24: # derived from this software without specific prior written permission.
25: #
26: # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27: # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28: # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29: # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
30: # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31: # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32: # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34: # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35: # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: # POSSIBILITY OF SUCH DAMAGE.
37: #
38:
39: header=false
40:
41: for option
42: do
43: case $option in
44: --header) header=true ;;
45: esac
46: done
47:
48: PROG=`basename $0`
49: cat <<EOF
50: /* automatically generated by $PROG, do not edit! */
51: #include <tme/common.h>
52: _TME_RCSID("\$Id: ieee754-misc-auto.sh,v 1.2 2005/05/11 00:13:33 fredette Exp $");
53:
54: EOF
55: if $header; then
56: :
57: else
58: cat <<EOF
59: #include <tme/ic/ieee754.h>
60: #include "softfloat-tme.h"
61: #include <math.h>
62: #ifdef HAVE_FLOAT_H
63: #include <float.h>
64: #endif
65: #ifdef HAVE_LIMITS_H
66: #include <limits.h>
67: #endif
68: EOF
69: fi
70:
71: # permute for the different precisions we want to support:
72: #
73: for precision in single double extended80 quad; do
74:
75: # get information about this precision:
76: #
77: _precision=`echo $0 | sed -e "s/$PROG/ieee754-precision.sh/"`
78: eval `sh ${_precision} ${precision}`
79:
80: # if we're generating a header:
81: #
82: if $header; then
83: cat <<EOF
84:
85: /* decide which builtin C floating-point type is the best match for
86: the IEEE 754 ${precision} precision format. if a builtin type matches
87: this format exactly, use that type, otherwise we assume that the
88: smallest builtin type that is at least ${size} bytes wide is the best
89: match. if no builtin type is at least that wide, we use long
90: double, or double if long double is not available: */
91: #if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_${capprecision}) != 0)
92: #define TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN TME_FLOAT_FORMAT_IEEE754_${capprecision}
93: #elif (_TME_SIZEOF_FLOAT >= ${size})
94: #define TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN TME_FLOAT_FORMAT_FLOAT
95: #elif (_TME_SIZEOF_DOUBLE >= ${size} || !defined(_TME_HAVE_LONG_DOUBLE))
96: #define TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN TME_FLOAT_FORMAT_DOUBLE
97: #else
98: #define TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN TME_FLOAT_FORMAT_LONG_DOUBLE
99: #endif
100:
101: /* typedef the builtin C floating-point type that is the best match
102: for the IEEE 754 ${precision} precision format: */
103: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
104: typedef float tme_ieee754_${precision}_builtin_t;
105: #define tme_float_value_ieee754_${precision}_builtin tme_float_value_float
106: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
107: typedef double tme_ieee754_${precision}_builtin_t;
108: #define tme_float_value_ieee754_${precision}_builtin tme_float_value_double
109: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE)
110: typedef long double tme_ieee754_${precision}_builtin_t;
111: #define tme_float_value_ieee754_${precision}_builtin tme_float_value_long_double
112: #endif
113:
114: /* this asserts that the float is either in IEEE 754 ${precision}
115: precision format, or in the best-match builtin type format. it
116: evaluates to nonzero if the float is in IEEE 754 ${precision}
117: precision format: */
118: #define tme_ieee754_${precision}_is_format(x) \\
119: (tme_float_assert_formats(x, \\
120: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN) \\
121: && tme_float_is_format(x, \\
122: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN, \\
123: TME_FLOAT_FORMAT_IEEE754_${capprecision}))
124:
125: /* this asserts that the float is either in IEEE 754 ${precision}
126: precision format, or in the best-match builtin type format. it
127: evaluates to nonzero if the float is in the best-match builtin
128: type format: */
129: #define tme_ieee754_${precision}_is_format_builtin(x) \\
130: (tme_float_assert_formats(x, \\
131: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN) \\
132: && tme_float_is_format(x, \\
133: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN, \\
134: TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN))
135:
136: /* this asserts that the float is either in IEEE 754 ${precision}
137: precision format, or in the best-match builtin type format. it
138: evaluates to nonzero if the float is a NaN: */
139: #define tme_ieee754_${precision}_is_nan(x) \\
140: (tme_float_assert_formats(x, \\
141: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN) \\
142: && tme_float_is_nan(x, \\
143: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN))
144:
145: /* this asserts that the float is either in IEEE 754 ${precision}
146: precision format, or in the best-match builtin type format. it
147: evaluates to nonzero if the float is an infinity: */
148: #define tme_ieee754_${precision}_is_inf(x) \\
149: (tme_float_assert_formats(x, \\
150: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN) \\
151: && tme_float_is_inf(x, \\
152: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN))
153:
154: /* this asserts that the float is either in IEEE 754 ${precision}
155: precision format, or in the best-match builtin type format. it
156: evaluates to nonzero if the float is a zero: */
157: #define tme_ieee754_${precision}_is_zero(x) \\
158: (tme_float_assert_formats(x, \\
159: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN) \\
160: && tme_float_is_zero(x, \\
161: TME_FLOAT_FORMAT_IEEE754_${capprecision} | TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN))
162:
163: /* tme_ieee754_${precision}_value_get(x, buffer) returns a pointer to
164: the value of x in IEEE 754 ${precision} precision format (i.e., it
165: returns a pointer to ${integral}). if x isn't already in this
166: format, it is converted into that format in the given buffer: */
167: #define tme_ieee754_${precision}_value_get(x, buffer) \\
168: (tme_ieee754_${precision}_is_format(x) \\
169: ? &(x)->tme_float_value_ieee754_${precision} \\
170: : tme_ieee754_${precision}_value_from_builtin((x)->tme_float_value_ieee754_${precision}_builtin, buffer))
171:
172: /* tme_ieee754_${precision}_value_set(x, y) sets the value of x to
173: y, in IEEE 754 ${precision} precision format (i.e., y is a ${integral}).
174: (the internal function _tme_ieee754_${precision}_value_set(x, t, y)
175: takes the type of y, which must be compatible with ${integral}): */
176: #define tme_ieee754_${precision}_value_set(x, y) \\
177: do { \\
178: (x)->tme_float_value_ieee754_${precision} = (y); \\
179: (x)->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision}; \\
180: } while (/* CONSTCOND */ 0)
181: #define _tme_ieee754_${precision}_value_set(x, t, y) \\
182: do { \\
183: *((t *) &(x)->tme_float_value_ieee754_${precision}) = (y); \\
184: (x)->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision}; \\
185: } while (/* CONSTCOND */ 0)
186:
187: /* tme_ieee754_${precision}_value_set_constant(x, y) sets the value of
188: x to the constant y (i.e., y is a const ${constant} *): */
189: #define tme_ieee754_${precision}_value_set_constant(x, y) \\
190: do { \\
191: EOF
192: x_value="(x)->tme_float_value_ieee754_${precision}"
193: case "${precision}" in
194: single)
195: echo " ${x_value} = *(y); \\"
196: ;;
197: double)
198: echo " ${x_value}.tme_value64_uint32_hi = (y)->tme_ieee754_double_constant_hi; \\"
199: echo " ${x_value}.tme_value64_uint32_lo = (y)->tme_ieee754_double_constant_lo; \\"
200: ;;
201: extended80)
202: echo " ${x_value}.tme_float_ieee754_extended80_sexp = (y)->tme_ieee754_extended80_constant_sexp; \\"
203: echo " ${x_value}.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = (y)->tme_ieee754_extended80_constant_significand_hi; \\"
204: echo " ${x_value}.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = (y)->tme_ieee754_extended80_constant_significand_lo; \\"
205: ;;
206: quad)
207: echo " ${x_value}.tme_float_ieee754_quad_hi.tme_value64_uint32_hi = (y)->tme_ieee754_quad_constant_hi_hi; \\"
208: echo " ${x_value}.tme_float_ieee754_quad_hi.tme_value64_uint32_lo = (y)->tme_ieee754_quad_constant_hi_lo; \\"
209: echo " ${x_value}.tme_float_ieee754_quad_lo.tme_value64_uint32_hi = (y)->tme_ieee754_quad_constant_lo_hi; \\"
210: echo " ${x_value}.tme_float_ieee754_quad_lo.tme_value64_uint32_lo = (y)->tme_ieee754_quad_constant_lo_lo; \\"
211: ;;
212: esac
213: cat <<EOF
214: (x)->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision}; \\
215: } while (/* CONSTCOND */ 0)
216:
217: /* tme_ieee754_${precision}_value_builtin_get(x) returns the value of
218: x as the builtin C type that is the best match for the IEEE 754
219: ${precision} precision format: */
220: #define tme_ieee754_${precision}_value_builtin_get(x) \\
221: (tme_ieee754_${precision}_is_format_builtin(x) \\
222: ? (x)->tme_float_value_ieee754_${precision}_builtin \\
223: : tme_ieee754_${precision}_value_to_builtin(&(x)->tme_float_value_ieee754_${precision}))
224:
225: /* tme_ieee754_${precision}_value_builtin_set(x, format, y) sets the value of
226: x to y, whose type is a builtin C type with format format. if the value of
227: y is a NaN or an infinity, y is stored in x in IEEE 754 ${precision}
228: precision format, otherwise y is stored in x as the builtin C type
229: that is the best match for the IEEE 754 ${precision} precision format: */
230: #define tme_ieee754_${precision}_value_builtin_set(x, format, y) \\
231: do { \\
232: /* set the value: */ \\
233: tme_float_value_builtin_set(x, format, y); \\
234: \\
235: /* if the result is a NaN: */ \\
236: if (tme_float_is_nan(x, format)) { \\
237: \\
238: /* use the proper default IEEE 754 ${precision} precision NaN: */ \\
239: (x)->tme_float_value_ieee754_${precision} = ieee754_ctl->tme_ieee754_ctl_default_nan_${precision}; \\
240: (x)->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision}; \\
241: } \\
242: \\
243: /* otherwise, if the result isn't already in IEEE 754 ${precision} precision format: */ \\
244: else if ((format) != TME_FLOAT_FORMAT_IEEE754_${capprecision}) { \\
245: \\
246: /* if the result is infinite: */ \\
247: if (tme_float_is_inf(x, format)) { \\
248: \\
249: /* use the IEEE 754 ${precision} precision infinity: */ \\
250: (x)->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision}; \\
251: (x)->tme_float_value_ieee754_${precision}${sexp} = ${mask_exp} | (tme_float_is_negative(x, (format)) ? ${mask_sign} : 0); \\
252: EOF
253: case "${precision}" in
254: single) ;;
255: double)
256: echo " (x)->tme_float_value_ieee754_double.tme_value64_uint32_lo = 0; \\"
257: ;;
258: extended80)
259: echo " (x)->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = 0; \\"
260: echo " (x)->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0; \\"
261: ;;
262: quad)
263: echo " (x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_lo = 0; \\"
264: echo " (x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_lo.tme_value64_uint32_hi = 0; \\"
265: echo " (x)->tme_float_value_ieee754_quad.tme_float_ieee754_quad_lo.tme_value64_uint32_lo = 0; \\"
266: ;;
267: esac
268: cat <<EOF
269: } \\
270: \\
271: /* otherwise, if the result isn't already the builtin C type that \\
272: is the best match for the IEEE 754 ${precision} precision format: */ \\
273: else if ((format) != TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN) { \\
274: \\
275: /* convert the result: */ \\
276: if ((format) == TME_FLOAT_FORMAT_FLOAT) { \\
277: (x)->tme_float_value_ieee754_${precision}_builtin = (x)->tme_float_value_float; \\
278: } \\
279: TME_FLOAT_IF_LONG_DOUBLE(else if ((format) == TME_FLOAT_FORMAT_LONG_DOUBLE) { \\
280: (x)->tme_float_value_ieee754_${precision}_builtin = (x)->tme_float_value_long_double; \\
281: }) \\
282: else { \\
283: assert((format) == TME_FLOAT_FORMAT_DOUBLE); \\
284: (x)->tme_float_value_ieee754_${precision}_builtin = (x)->tme_float_value_double; \\
285: } \\
286: } \\
287: } \\
288: } while (/* CONSTCOND */ 0)
289:
290: /* this converts a value from IEEE 754 ${precision} precision format
291: into the builtin C type that is the best match for that format: */
292: tme_ieee754_${precision}_builtin_t tme_ieee754_${precision}_value_to_builtin _TME_P((const ${integral} *));
293:
294: /* this converts a value from the builtin C type that is the best
295: match for the IEEE 754 ${precision} precision format, into that
296: format: */
297: const ${integral} *tme_ieee754_${precision}_value_from_builtin _TME_P((tme_ieee754_${precision}_builtin_t, ${integral} *));
298:
299: /* this does a NaN check for an IEEE 754 ${precision} precision monadic function: */
300: int tme_ieee754_${precision}_check_nan_monadic _TME_P((struct tme_ieee754_ctl *, const struct tme_float *, struct tme_float *));
301:
302: /* this does a NaN check for an IEEE 754 ${precision} precision dyadic function: */
303: int tme_ieee754_${precision}_check_nan_dyadic _TME_P((struct tme_ieee754_ctl *, const struct tme_float *, const struct tme_float *, struct tme_float *));
304: EOF
305:
306: # emit the prototypes for the from-integer conversion
307: # functions:
308: #
309: for convert in int32 int64; do
310:
311: cond=1
312: case ${convert} in
313: int32) convert_builtin="tme_uint32_t" ;;
314: int64) convert_builtin="tme_uint64_t" ; cond="defined(TME_HAVE_INT64_T)" ;;
315: esac
316:
317: if test "${cond}" != 1; then
318: echo ""
319: echo "#if ${cond}"
320: fi
321:
322: echo ""
323: echo "/* this converts a ${convert_builtin} to a ${precision}: */"
324: echo "void tme_ieee754_${precision}_from_${convert} _TME_P((${convert_builtin}, struct tme_float *));"
325:
326: if test "${cond}" != 1; then
327: echo ""
328: echo "#endif /* ${cond} */"
329: fi
330: done
331:
332: # permute over the radices:
333: #
334: for radix in 10; do
335:
336: cat <<EOF
337:
338: /* this converts an in-range IEEE 754 ${precision} precision value into its
339: radix ${radix} mantissa and exponent. the mantissa is either zero, or
340: in the range [1,${radix}): */
341: void tme_ieee754_${precision}_radix${radix}_mantissa_exponent _TME_P((struct tme_ieee754_ctl *, const struct tme_float *, struct tme_float *, struct tme_float *));
342:
343: /* this scales an IEEE 754 ${precision} precision value by adding n to its
344: radix ${radix} exponent: */
345: void tme_ieee754_${precision}_radix${radix}_scale _TME_P((struct tme_ieee754_ctl *, const struct tme_float *, const struct tme_float *, struct tme_float *));
346:
347: EOF
348: done
349:
350: # otherwise, we're not generating a header:
351: #
352: else
353:
354: cat <<EOF
355:
356: /* this converts a value from IEEE 754 ${precision} precision format
357: to the builtin C type that is the best match for that format: */
358: tme_ieee754_${precision}_builtin_t
359: tme_ieee754_${precision}_value_to_builtin(const ${integral} *x_ieee754)
360: {
361: tme_ieee754_${precision}_builtin_t x_builtin;
362: tme_uint32_t exponent;
363: tme_uint32_t sign;
364: tme_uint32_t chunk;
365: tme_uint32_t fracor;
366:
367: /* get x's biased exponent: */
368: exponent = TME_FIELD_MASK_EXTRACTU((*x_ieee754)${sexp}, ${mask_exp});
369:
370: /* convert the fraction one 16-bit chunk at a time, and track
371: a bitwise-or of all of the fraction bits: */
372: EOF
373: chunk_i=0
374: while true; do
375: eval "chunk_member=\$chunk_member_${chunk_i} ; chunk_mask=\$chunk_mask_${chunk_i}"
376: if test "x${chunk_member}" = xx; then
377: break
378: fi
379: echo " chunk = TME_FIELD_MASK_EXTRACTU((*x_ieee754)${chunk_member}, ${chunk_mask});"
380: if test ${chunk_i} = 0; then
381: echo " fracor = chunk;"
382: if ${implicit}; then
383: echo " /* if the exponent is nonzero, add the implicit integer bit: */"
384: echo " if (exponent != 0) chunk |= ((${chunk_mask} / _TME_FIELD_MASK_FACTOR(${chunk_mask})) + 1);"
385: fi
386: echo " x_builtin = chunk;"
387: else
388: echo " fracor |= chunk;"
389: echo " x_builtin = (x_builtin * 65536) + chunk;"
390: fi
391: chunk_i=`expr ${chunk_i} + 1`
392: done
393: cat <<EOF
394:
395: /* get x's sign bit: */
396: sign = ((*x_ieee754)${sexp} & ${mask_sign});
397:
398: /* if the exponent is the biased maximum, x is either an infinity or a NaN: */
399: if (exponent == ${exp_biased_max}) {
400:
401: /* if the fraction is nonzero, x is a NaN. x must not be a NaN,
402: because we were supposed to catch this earlier: */
403: assert (fracor == 0);
404:
405: /* x is an infinity. construct a builtin infinity: */
406: /* XXX FIXME - we assume that multiplying the maximum builtin
407: value by +10 or -10 will not yield a value whose magnitude is
408: less than the maximum builtin value: */
409: x_builtin =
410: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
411: FLOAT_MAX_FLOAT
412: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
413: FLOAT_MAX_DOUBLE
414: #elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
415: FLOAT_MAX_LONG_DOUBLE
416: #endif
417: * (sign ? -10 : 10);
418: }
419:
420: /* if the exponent is the biased minimum and the fraction is
421: all-bits-zero, x is a zero: */
422: else if (exponent == 0
423: && fracor == 0) {
424:
425: /* construct a builtin zero: */
426: /* XXX FIXME - we assume that dividing the minimum builtin value
427: by +10 or -10 (in case the builtin type is radix 10) will yield
428: a value whose magnitude is not greater than the minimum builtin
429: value: */
430: x_builtin =
431: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
432: FLOAT_MIN_FLOAT
433: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
434: FLOAT_MIN_DOUBLE
435: #elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
436: FLOAT_MIN_LONG_DOUBLE
437: #endif
438: / (sign ? -10 : 10);
439: }
440:
441: /* otherwise, x is an in-range value that needs to be converted: */
442: else {
443:
444: /* scale the result by the unbiased exponent, adjusted by the
445: number of fraction bits (which are currently to the left of the
446: floating point in x_builtin): */
447: x_builtin =
448: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
449: tme_float_radix2_scale_float
450: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
451: tme_float_radix2_scale_double
452: #elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
453: tme_float_radix2_scale_long_double
454: #endif
455: (x_builtin, (exponent - ${exp_bias}) - ${fracbits});
456:
457: if (sign) {
458: x_builtin = 0 - x_builtin;
459: }
460: }
461:
462: /* done: */
463: return (x_builtin);
464: }
465:
466: /* this converts a value from the builtin C type that is the best
467: match for the IEEE 754 ${precision} precision format, to that
468: format: */
469: const ${integral} *
470: tme_ieee754_${precision}_value_from_builtin(tme_ieee754_${precision}_builtin_t x_builtin, ${integral} *x_ieee754)
471: {
472: tme_int32_t exponent;
473: tme_uint32_t chunk;
474:
475: /* x must not be a NaN or an infinity: */
476: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
477: assert (!isnanf(x_builtin));
478: assert (!isinff(x_builtin));
479: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
480: assert (!isnan(x_builtin));
481: assert (!isinf(x_builtin));
482: #elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
483: assert (!isnan(x_builtin));
484: assert (!isinf(x_builtin));
485: #endif
486:
487: /* get the mantissa and exponent of x: */
488: x_builtin =
489: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
490: tme_float_radix2_mantissa_exponent_float
491: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
492: tme_float_radix2_mantissa_exponent_double
493: #elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
494: tme_float_radix2_mantissa_exponent_long_double
495: #endif
496: (x_builtin, &exponent);
497:
498: /* zero the IEEE 754 version: */
499: memset((char *) x_ieee754, 0, sizeof((*x_ieee754)));
500:
501: /* set x's sign bit: */
502: if (x_builtin < 0) {
503: (*x_ieee754)${sexp} |= ${mask_sign};
504: x_builtin = -x_builtin;
505: }
506:
507: /* if x is zero, return now: */
508: if (x_builtin == 0) {
509: return (x_ieee754);
510: }
511:
512: /* bias the exponent: */
513: exponent += ${exp_bias};
514:
515: /* if the biased exponent is greater than or equal to the biased
516: maximum, we must represent x as an infinity: */
517: if (exponent >= (tme_int32_t) ${exp_biased_max}) {
518:
519: /* we do this by just setting the biased exponent to the biased
520: maximum: */
521: exponent = ${exp_biased_max};
522: }
523:
524: /* otherwise, x will be either a normalized number, a denormalized
525: number, or possibly a zero: */
526: else {
527:
528: /* if the biased exponent is less than or equal to the biased
529: minimum, x will be a denormalized number (possibly so
530: denormalized that it becomes a zero): */
531: if (exponent <= 0) {
532:
533: /* scale x into a denormalized number: */
534: assert (x_builtin >= 1);
535: x_builtin =
536: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_FLOAT)
537: tme_float_radix2_scale_float
538: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_DOUBLE)
539: tme_float_radix2_scale_double
540: #elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_LONG_DOUBLE))
541: tme_float_radix2_scale_long_double
542: #endif
543: (x_builtin, exponent - 1);
544: assert (x_builtin < 1);
545: exponent = 0;
546: }
547:
548: /* convert the mantissa, one 16-bit chunk at a time: */
549: EOF
550: chunk_i=0
551: while true; do
552: eval "chunk_member=\$chunk_member_${chunk_i} ; chunk_mask=\$chunk_mask_${chunk_i}"
553: if test "x${chunk_member}" = xx; then
554: break
555: fi
556: factor="((${chunk_mask} / _TME_FIELD_MASK_FACTOR(${chunk_mask})) + 1)"
557: if test ${chunk_i} = 0; then
558: if ${implicit}; then
559: echo " /* remove any implicit integer bit: */"
560: echo " if (x_builtin >= 1) {"
561: echo " x_builtin -= 1;"
562: echo " }"
563: else
564: factor="(${factor} / 2)"
565: fi
566: fi
567: echo " x_builtin = x_builtin * ${factor};"
568: echo " chunk = x_builtin;"
569: echo " x_builtin -= chunk;"
570: echo " TME_FIELD_MASK_DEPOSITU((*x_ieee754)${chunk_member}, ${chunk_mask}, chunk);"
571: chunk_i=`expr ${chunk_i} + 1`
572: factor=65536
573: done
574: cat <<EOF
575: }
576:
577: /* set x's biased exponent: */
578: TME_FIELD_MASK_DEPOSITU((*x_ieee754)${sexp}, ${mask_exp}, exponent);
579:
580: /* done: */
581: return (x_ieee754);
582: }
583: EOF
584:
585: # emit the NaN check functions:
586: #
587: for monadic in true false; do
588: if ${monadic}; then type=monadic; else type=dyadic; fi
589:
590: echo ""
591: echo "/* this does a NaN check for an IEEE 754 ${precision} precision ${type} function: */"
592: echo "int"
593: echo -n "tme_ieee754_${precision}_check_nan_${type}(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0"
594: if ${monadic}; then :; else
595: echo -n ", const struct tme_float *src1"
596: fi
597: echo ", struct tme_float *dst)"
598: echo "{"
599: echo " const ${integral} *nan0;"
600: if $monadic; then :; else
601: echo " const ${integral} *nan1;"
602: fi
603: echo ""
604: echo " /* check for a NaN operand: */"
605: echo " nan0 = NULL;"
606: echo " if (tme_ieee754_${precision}_is_nan(src0)) {"
607: echo " assert (src0->tme_float_format == TME_FLOAT_FORMAT_IEEE754_${capprecision});"
608: echo " nan0 = &src0->tme_float_value_ieee754_${precision};"
609: echo " }"
610: if $monadic; then nan1=nan0; else
611: nan1=nan1
612: echo " nan1 = nan0;"
613: echo " if (tme_ieee754_${precision}_is_nan(src1)) {"
614: echo " assert (src1->tme_float_format == TME_FLOAT_FORMAT_IEEE754_${capprecision});"
615: echo " nan1 = &src1->tme_float_value_ieee754_${precision};"
616: echo " if (nan0 == NULL) {"
617: echo " nan0 = nan1;"
618: echo " }"
619: echo " }"
620: fi
621: echo ""
622: echo " /* if we have a NaN operand: */"
623: echo " if (__tme_predict_false(nan0 != NULL)) {"
624: echo ""
625: echo " /* propagate a NaN: */"
626: echo " dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision};"
627: echo " (*ieee754_ctl->tme_ieee754_ctl_nan_from_nans_${precision})"
628: echo " (ieee754_ctl, nan0, ${nan1}, &dst->tme_float_value_ieee754_${precision});"
629: echo " return (TRUE);"
630: echo " }"
631: echo ""
632: echo " return (FALSE);"
633: echo "}"
634: done
635:
636: # emit the from-integer conversion functions:
637: #
638: for convert in int32 int64; do
639:
640: cond=1
641: case ${convert} in
642: int32) convert_builtin="tme_uint32_t" ;;
643: int64) convert_builtin="tme_uint64_t" ; cond="defined(TME_HAVE_INT64_T)" ;;
644: esac
645:
646: if test "${cond}" != 1; then
647: echo ""
648: echo "#if ${cond}"
649: fi
650:
651: echo ""
652: echo "/* this converts a ${convert_builtin} to a ${precision}: */"
653: echo "void"
654: echo "tme_ieee754_${precision}_from_${convert}(${convert_builtin} src, struct tme_float *dst)"
655: echo "{"
656: echo " _tme_ieee754_${precision}_value_set(dst, ${precision_sf}, ${convert}_to_${precision_sf}(src));"
657: echo "}"
658:
659: if test "${cond}" != 1; then
660: echo ""
661: echo "#endif /* ${cond} */"
662: fi
663: done
664:
665: echo ""
666: echo "/* this converts a ${precision} to an int32: */"
667: echo "tme_int32_t"
668: echo "tme_ieee754_${precision}_to_int32(const struct tme_float *src)"
669: echo "{"
670: echo " ${integral} src_buffer;"
671: echo " return (${precision_sf}_to_int32(*((const ${precision_sf} *) tme_ieee754_${precision}_value_get(src, &src_buffer))));"
672: echo "}"
673:
674: # permute over the radices:
675: #
676: for radix in 2 10; do
677:
678: # XXX FIXME - for now, skip quad precisions. this is just
679: # laziness over generating the constants:
680: #
681: if test "${precision}" = quad; then continue; fi
682:
683: cat <<EOF
684:
685: /* this converts an in-range IEEE 754 ${precision} precision value into its
686: radix ${radix} mantissa and exponent. the mantissa is either zero, or
687: in the range [1,${radix}): */
688: void
689: tme_ieee754_${precision}_radix${radix}_mantissa_exponent(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src, struct tme_float *_mantissa, struct tme_float *_exponent)
690: {
691: tme_int32_t exponent;
692: EOF
693: if test ${radix} != 2; then
694: cat <<EOF
695: #if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_${capprecision}) == 0)
696: ${integral} value_ieee754_buffer;
697: struct tme_float value_buffer;
698: struct tme_float zero_buffer;
699: struct tme_float one_buffer;
700: struct tme_float constant_buffer;
701: struct tme_float radix_buffer;
702: ${precision_sf} * const value = (${precision_sf} *) &value_buffer.tme_float_value_ieee754_${precision};
703: const ${precision_sf} * const zero = (${precision_sf} *) &zero_buffer.tme_float_value_ieee754_${precision};
704: const ${precision_sf} * const one = (${precision_sf} *) &one_buffer.tme_float_value_ieee754_${precision};
705: const ${precision_sf} * const constant = (${precision_sf} *) &constant_buffer.tme_float_value_ieee754_${precision};
706: const ${precision_sf} * const radix = (${precision_sf} *) &radix_buffer.tme_float_value_ieee754_${precision};
707: tme_uint32_t exponent_bit;
708: int negate;
709: #endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_${capprecision}) == 0) */
710: EOF
711: fi
712: cat <<EOF
713:
714: /* check for a NaN operand: */
715: if (__tme_predict_false(tme_ieee754_${precision}_check_nan_monadic(ieee754_ctl, src, _mantissa))) {
716: if (_exponent != NULL) {
717: *_exponent = *_mantissa;
718: }
719: return;
720: }
721:
722: /* if this is an infinity: */
723: if (tme_ieee754_${precision}_is_inf(src)) {
724:
725: /* return a NaN: */
726: _mantissa->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision};
727: _mantissa->tme_float_value_ieee754_${precision} = ieee754_ctl->tme_ieee754_ctl_default_nan_${precision};
728: if (_exponent != NULL) {
729: *_exponent = *_mantissa;
730: }
731: return;
732: }
733: EOF
734: if test ${radix} = 2; then
735: echo ""
736: echo " /* extract the unbiased exponent: */"
737: echo " exponent = TME_FIELD_MASK_EXTRACTU(src->tme_float_value_ieee754_${precision}${sexp}, ${mask_exp});"
738: echo " exponent -= ${exp_bias};"
739: echo ""
740: echo " /* the mantissa is the source with a biased zero for the exponent: */"
741: echo " *_mantissa = *src;"
742: echo " TME_FIELD_MASK_DEPOSITU(_mantissa->tme_float_value_ieee754_${precision}${sexp}, ${mask_exp}, ${exp_bias});"
743: else
744: cat <<EOF
745:
746: /* if a builtin type matches the IEEE 754 ${precision} format exactly,
747: use the corresponding mantissa-exponent function: */
748: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision} == TME_FLOAT_FORMAT_FLOAT)
749: tme_ieee754_${precision}_value_builtin_set
750: (_mantissa,
751: TME_FLOAT_FORMAT_FLOAT,
752: tme_float_radix${radix}_mantissa_exponent_float(tme_ieee754_${precision}_value_builtin_get(src), &exponent));
753: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision} == TME_FLOAT_FORMAT_DOUBLE)
754: tme_ieee754_${precision}_value_builtin_set
755: (_mantissa,
756: TME_FLOAT_FORMAT_DOUBLE,
757: tme_float_radix${radix}_mantissa_exponent_double(tme_ieee754_${precision}_value_builtin_get(src), &exponent));
758: #elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_${capprecision} == TME_FLOAT_FORMAT_LONG_DOUBLE))
759: tme_ieee754_${precision}_value_builtin_set
760: (_mantissa,
761: TME_FLOAT_FORMAT_LONG_DOUBLE,
762: tme_float_radix${radix}_mantissa_exponent_long_double(tme_ieee754_${precision}_value_builtin_get(src), &exponent));
763: #else
764:
765: /* get this value and some constants: */
766: tme_ieee754_${precision}_value_set(&value_buffer, *tme_ieee754_${precision}_value_get(src, &value_ieee754_buffer));
767: tme_ieee754_${precision}_value_set_constant(&zero_buffer, &tme_ieee754_${precision}_constant_zero);
768: tme_ieee754_${precision}_value_set_constant(&one_buffer, &tme_ieee754_${precision}_constant_one);
769: tme_ieee754_${precision}_value_set_constant(&radix_buffer, &tme_ieee754_${precision}_constant_${radix}e2ex[0]);
770:
771: /* take the magnitude of the value, but remember if it was negative: */
772: negate = ${precision_sf}_lt(*value, *zero);
773: if (negate) {
774: *value = ${precision_sf}_sub(*zero, *value);
775: }
776:
777: /* start with an exponent of zero: */
778: exponent = 0;
779:
780: /* if the value is nonzero: */
781: if (!${precision_sf}_eq(*value, *zero)) {
782:
783: /* while the value is less than one: */
784: exponent_bit = TME_ARRAY_ELS(tme_ieee754_${precision}_constant_${radix}e_minus_2ex) - 1;
785: tme_ieee754_${precision}_value_set_constant(&constant_buffer, &tme_ieee754_${precision}_constant_${radix}e_minus_2ex[exponent_bit]);
786: for (; ${precision_sf}_lt(*value, *one); ) {
787:
788: /* if value is less than or equal to ${radix}^-(2^exponent_bit),
789: divide value by ${radix}^-(2^exponent_bit), and subtract 2^exponent_bit
790: from exponent: */
791: if (${precision_sf}_le(*value, *constant)
792: || exponent_bit == 0) {
793: *value = ${precision_sf}_div(*value, *constant);
794: exponent -= (1 << exponent_bit);
795: }
796:
797: /* otherwise, move to the next exponent bit: */
798: else {
799: exponent_bit--;
800: tme_ieee754_${precision}_value_set_constant(&constant_buffer, &tme_ieee754_${precision}_constant_${radix}e_minus_2ex[exponent_bit]);
801: }
802: }
803:
804: /* while the value is greater than ${radix}: */
805: exponent_bit = TME_ARRAY_ELS(tme_ieee754_${precision}_constant_${radix}e2ex) - 1;
806: tme_ieee754_${precision}_value_set_constant(&constant_buffer, &tme_ieee754_${precision}_constant_${radix}e2ex[exponent_bit]);
807: for (; !(${precision_sf}_le(*value, *radix)) ; ) {
808:
809: /* if value is greater than or equal to ${radix}^(2^exponent_bit),
810: divide value by ${radix}^(2^exponent_bit), and add 2^exponent_bit
811: to exponent: */
812: if (!(${precision_sf}_lt(*value, *constant))
813: || exponent_bit == 0) {
814: *value = ${precision_sf}_div(*value, *constant);
815: exponent += (1 << exponent_bit);
816: }
817:
818: /* otherwise, move to the next exponent bit: */
819: else {
820: exponent_bit--;
821: tme_ieee754_${precision}_value_set_constant(&constant_buffer, &tme_ieee754_${precision}_constant_${radix}e2ex[exponent_bit]);
822: }
823: }
824:
825: /* if the value was originally negative, negate the mantissa: */
826: if (negate) {
827: *value = ${precision_sf}_sub(*zero, *value);
828: }
829:
830: /* return the mantissa: */
831: _tme_ieee754_${precision}_value_set(_mantissa, ${precision_sf}, *value);
832: }
833: #endif
834: EOF
835: fi
836: cat <<EOF
837:
838: /* return the exponent: */
839: if (_exponent != NULL) {
840: _tme_ieee754_${precision}_value_set(_exponent, ${precision_sf}, int32_to_${precision_sf}(exponent));
841: }
842: }
843:
844: /* this scales an IEEE 754 ${precision} precision value by adding n to its
845: radix ${radix} exponent: */
846: void
847: tme_ieee754_${precision}_radix${radix}_scale(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, const struct tme_float *src1, struct tme_float *dst)
848: {
849: ${integral} src_buffer;
850: tme_int8_t rounding_mode;
851: tme_int32_t _n;
852: #if ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_${capprecision}) == 0)
853: tme_int32_t exponent;
854: tme_uint32_t exponent_bit, n;
855: ${precision_sf} * const value = (${precision_sf} *) &dst->tme_float_value_ieee754_${precision};
856: struct tme_float constant_buffer;
857: const ${precision_sf} * const constant = (${precision_sf} *) &constant_buffer.tme_float_value_ieee754_${precision};
858: #endif /* ((TME_FLOAT_FORMATS_BUILTIN & TME_FLOAT_FORMAT_IEEE754_${capprecision}) == 0) */
859:
860: /* check for a NaN operand: */
861: if (__tme_predict_false(tme_ieee754_${precision}_check_nan_dyadic(ieee754_ctl, src0, src1, dst))) {
862: return;
863: }
864:
865: /* if the exponent is an infinity: */
866: if (tme_ieee754_${precision}_is_inf(src1)) {
867:
868: /* return a NaN: */
869: dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision};
870: dst->tme_float_value_ieee754_${precision} = ieee754_ctl->tme_ieee754_ctl_default_nan_${precision};
871: return;
872: }
873:
874: /* if the operand is a zero or an infinity: */
875: if (tme_ieee754_${precision}_is_zero(src1)
876: || tme_ieee754_${precision}_is_inf(src1)) {
877:
878: /* return the operand unchanged: */
879: *dst = *src0;
880: return;
881: }
882:
883: /* truncate the exponent to an integer, using the round-to-zero mode: */
884: rounding_mode = ieee754_ctl->tme_ieee754_ctl_rounding_mode;
885: ieee754_ctl->tme_ieee754_ctl_rounding_mode = TME_FLOAT_ROUND_TO_ZERO;
886: _n = ${precision_sf}_to_int32(*((const ${precision_sf} *) tme_ieee754_${precision}_value_get(src1, &src_buffer)));
887: ieee754_ctl->tme_ieee754_ctl_rounding_mode = rounding_mode;
888:
889: /* if a builtin type matches the IEEE 754 ${precision} format exactly,
890: use the corresponding mantissa-exponent function: */
891: #if (TME_FLOAT_FORMAT_IEEE754_${capprecision} == TME_FLOAT_FORMAT_FLOAT)
892: tme_ieee754_${precision}_value_builtin_set
893: (dst,
894: TME_FLOAT_FORMAT_FLOAT,
895: tme_float_radix${radix}_scale_float(tme_ieee754_${precision}_value_builtin_get(src0), _n));
896: #elif (TME_FLOAT_FORMAT_IEEE754_${capprecision} == TME_FLOAT_FORMAT_DOUBLE)
897: tme_ieee754_${precision}_value_builtin_set
898: (dst,
899: TME_FLOAT_FORMAT_DOUBLE,
900: tme_float_radix${radix}_scale_double(tme_ieee754_${precision}_value_builtin_get(src0), _n));
901: #elif (defined(_TME_HAVE_LONG_DOUBLE) && (TME_FLOAT_FORMAT_IEEE754_${capprecision} == TME_FLOAT_FORMAT_LONG_DOUBLE))
902: tme_ieee754_${precision}_value_builtin_set
903: (dst,
904: TME_FLOAT_FORMAT_LONG_DOUBLE,
905: tme_float_radix${radix}_scale_long_double(tme_ieee754_${precision}_value_builtin_get(src0), _n));
906: #else
907:
908: /* start this value: */
909: tme_ieee754_${precision}_value_set(dst, *tme_ieee754_${precision}_value_get(src0, &src_buffer));
910:
911: /* start with the most significant exponent bit: */
912: exponent_bit = TME_ARRAY_ELS(tme_ieee754_${precision}_constant_${radix}e2ex) - 1;
913: exponent = (1 << exponent_bit);
914: tme_ieee754_${precision}_value_set_constant(&constant_buffer, &tme_ieee754_${precision}_constant_${radix}e2ex[exponent_bit]);
915:
916: /* if n is negative: */
917: if (_n < 0) {
918:
919: for (n = 0 - _n; n > 0;) {
920: if (n >= exponent || exponent == 1) {
921: *value = ${precision_sf}_div(*value, *constant);
922: n -= exponent;
923: }
924: else {
925: exponent >>= 1;
926: exponent_bit--;
927: tme_ieee754_${precision}_value_set_constant(&constant_buffer, &tme_ieee754_${precision}_constant_${radix}e2ex[exponent_bit]);
928: }
929: }
930: }
931:
932: /* otherwise, n is positive: */
933: else {
934: for (n = _n; n > 0;) {
935: if (n >= exponent || exponent == 1) {
936: *value = ${precision_sf}_mul(*value, *constant);
937: n -= exponent;
938: }
939: else {
940: exponent >>= 1;
941: exponent_bit--;
942: tme_ieee754_${precision}_value_set_constant(&constant_buffer, &tme_ieee754_${precision}_constant_${radix}e2ex[exponent_bit]);
943: }
944: }
945: }
946: #endif
947: }
948: EOF
949: done
950:
951: fi
952: done
953:
954: # done:
955: #
956: exit 0;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.