|
|
1.1 root 1: #! /bin/sh
2:
1.1.1.2 ! root 3: # $Id: float-auto.sh,v 1.2 2007/08/24 00:55:33 fredette Exp $
1.1 root 4:
5: # generic/float-auto.sh - automatically generates C code for floating
6: # point conversion functions:
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: for option
41: do
42: case $option in
43: --header) header=true ;;
44: esac
45: done
46:
47: PROG=`basename $0`
48: cat <<EOF
49: /* automatically generated by $PROG, do not edit! */
50:
51: EOF
52: if $header; then :; else
53: cat <<EOF
54: #include <tme/common.h>
1.1.1.2 ! root 55: _TME_RCSID("\$Id: float-auto.sh,v 1.2 2007/08/24 00:55:33 fredette Exp $");
1.1 root 56:
57: /* includes: */
58: #include <tme/generic/float.h>
59:
60: EOF
61: fi
62:
63: # permute over the builtin types:
64: #
65: for _builtin_type in float double long_double; do
66:
67: # make the builtin type without underscores, and in all caps:
68: #
69: builtin_type=`echo ${_builtin_type} | sed -e 's/_/ /g'`
70: _BUILTIN_TYPE=`echo ${_builtin_type} | tr 'a-z' 'A-Z'`
71:
72: # dispatch on the builtin type to open any protection:
73: #
74: case ${_builtin_type} in
75: long_double)
76: echo ; echo "#ifdef _TME_HAVE_${_BUILTIN_TYPE}" ;;
77: *) ;;
78: esac
79:
1.1.1.2 ! root 80: # if we're generating a header:
! 81: #
! 82: if $header; then
! 83: cat <<EOF
! 84:
! 85: /* if possible, this returns a positive or negative infinity
! 86: ${builtin_type}, otherwise, this returns the ${builtin_type} value
! 87: closest to that infinity: */
! 88: ${builtin_type} tme_float_infinity_${_builtin_type} _TME_P((int));
! 89:
! 90: /* if possible, this returns a negative zero ${builtin_type}.
! 91: otherwise, this returns the negative ${builtin_type} value closest
! 92: to zero: */
! 93: ${builtin_type} tme_float_negative_zero_${_builtin_type} _TME_P((void));
! 94: EOF
! 95: else
! 96: cat <<EOF
! 97:
! 98: /* if possible, this returns a positive or negative infinity
! 99: ${builtin_type}, otherwise, this returns the ${builtin_type} value
! 100: closest to that infinity: */
! 101: ${builtin_type}
! 102: tme_float_infinity_${_builtin_type}(int negative)
! 103: {
! 104: static int inf_set_${_builtin_type};
! 105: static ${builtin_type} inf_${_builtin_type}[2];
! 106: ${builtin_type} inf_test;
! 107: int negative_i;
! 108:
! 109: /* make sure that negative can index the inf_${_builtin_type} array: */
! 110: negative = !!negative;
! 111:
! 112: /* if the ${builtin_type} infinities have already been set: */
! 113: if (__tme_predict_true(inf_set_${_builtin_type})) {
! 114: return (inf_${_builtin_type}[negative]);
! 115: }
! 116:
! 117: /* the ${builtin_type} infinities will be set now: */
! 118: inf_set_${_builtin_type} = TRUE;
! 119:
! 120: /* set the positive and negative infinities: */
! 121: for (negative_i = 0; negative_i < 2; negative_i++) {
! 122:
! 123: /* start with the limit maximum positive value or limit minimum
! 124: negative value. double this value until either it doesn't
! 125: change or it isn't closer to the desired infinity, and then
! 126: use the previous value: */
! 127: inf_test = FLOAT_MAX_${_BUILTIN_TYPE};
! 128: if (negative_i) {
! 129: inf_test = -inf_test;
! 130: }
! 131: do {
! 132: memcpy((char *) &inf_${_builtin_type}[negative_i], (char *) &inf_test, sizeof(inf_test));
! 133: inf_test *= 2;
! 134: } while (memcmp((char *) &inf_${_builtin_type}[negative_i], (char *) &inf_test, sizeof(inf_test)) != 0
! 135: && (negative_i
! 136: ? inf_test < inf_${_builtin_type}[negative_i]
! 137: : inf_test > inf_${_builtin_type}[negative_i]));
! 138:
! 139: /* try to generate the actual infinity by dividing one or negative
! 140: one by zero. if this value is closer to the desired infinity,
! 141: use it: */
! 142: inf_test = (negative_i ? -1.0 : 1.0) / 0.0;
! 143: if (negative_i
! 144: ? inf_test < inf_${_builtin_type}[negative_i]
! 145: : inf_test > inf_${_builtin_type}[negative_i]) {
! 146: inf_${_builtin_type}[negative_i] = inf_test;
! 147: }
! 148: }
! 149:
! 150: /* return the desired infinity: */
! 151: return (inf_${_builtin_type}[negative]);
! 152: }
! 153:
! 154: /* if possible, this returns a negative zero ${builtin_type}.
! 155: otherwise, this returns the negative ${builtin_type} value closest
! 156: to zero: */
! 157: ${builtin_type}
! 158: tme_float_negative_zero_${_builtin_type}(void)
! 159: {
! 160: static int nzero_set_${_builtin_type};
! 161: static ${builtin_type} nzero_${_builtin_type};
! 162: ${builtin_type} constant_pzero;
! 163: ${builtin_type} constant_nzero;
! 164: ${builtin_type} nzero_test;
! 165:
! 166: /* if the ${builtin_type} negative zero has already been set: */
! 167: if (__tme_predict_true(nzero_set_${_builtin_type})) {
! 168: return (nzero_${_builtin_type});
! 169: }
! 170:
! 171: /* the ${builtin_type} negative zero will be set now: */
! 172: nzero_set_${_builtin_type} = TRUE;
! 173:
! 174: /* make a +0.0 and a -0.0, that we can do bit-for-bit comparisons with.
! 175: NB that sizeof(${builtin_type}) may cover more bits than are actually
! 176: used by a ${builtin_type}: */
! 177: memset((char *) &constant_pzero, 0, sizeof(constant_pzero));
! 178: memset((char *) &constant_nzero, 0, sizeof(constant_nzero));
! 179: constant_pzero = +0.0;
! 180: constant_nzero = -0.0;
! 181:
! 182: /* if -0.0 * -0.0 is bit-for-bit different from -0.0 and is
! 183: bit-for-bit identical to +0.0, use -0.0: */
! 184: memset((char *) &nzero_test, 0, sizeof(nzero_test));
! 185: nzero_test = constant_nzero * constant_nzero;
! 186: if (memcmp((char *) &constant_nzero, (char *) &nzero_test, sizeof(nzero_test)) != 0
! 187: && memcmp((char *) &constant_pzero, (char *) &nzero_test, sizeof(nzero_test)) == 0) {
! 188: return (nzero_${_builtin_type} = constant_nzero);
! 189: }
! 190:
! 191: /* otherwise, start with the limit maximum negative value (which is
! 192: zero minus the limit minimum positive value). halve this value
! 193: until either it doesn't change or it becomes positive zero, and
! 194: then use the previous value: */
! 195: nzero_test = 0 - FLOAT_MIN_${_BUILTIN_TYPE};
! 196: do {
! 197: memcpy((char *) &nzero_${_builtin_type}, (char *) &nzero_test, sizeof(nzero_test));
! 198: nzero_test = nzero_test / 2;
! 199: } while (memcmp((char *) &nzero_${_builtin_type}, (char *) &nzero_test, sizeof(nzero_test)) != 0
! 200: && memcmp((char *) &constant_pzero, (char *) &nzero_test, sizeof(nzero_test)) != 0);
! 201: return (nzero_${_builtin_type});
! 202: }
! 203: EOF
! 204: fi
! 205:
! 206:
1.1 root 207: # permute over the radices:
208: #
209: for radix in 2 10; do
210:
211: # if we're generating a header:
212: #
213: if $header; then
214: cat <<EOF
215:
216: /* this returns the radix ${radix} mantissa and exponent of an in-range ${builtin_type}.
217: the mantissa is either zero, or in the range [1,${radix}): */
218: ${builtin_type} tme_float_radix${radix}_mantissa_exponent_${_builtin_type} _TME_P((${builtin_type}, tme_int32_t *));
219:
220: /* this scales a value by adding n to its radix ${radix} exponent: */
221: ${builtin_type} tme_float_radix${radix}_scale_${_builtin_type} _TME_P((${builtin_type}, tme_int32_t));
222: EOF
223: continue
224: fi
225:
226: # permute over the sign of the exponent:
227: #
228: for _sign in pos neg; do
229:
230: # make the sign into two operators:
231: #
232: if test ${_sign} = pos; then sign= ; combine='*' ; else sign=- ; combine='/' ; fi
233:
234: echo ""
235: echo "/* a series of ${builtin_type} values of the form ${radix}^${sign}x, where x is a power of two: */"
236: echo "static const ${builtin_type} _tme_float_radix${radix}_exponent_bits_${_builtin_type}_${_sign}[] = {"
237: exponent=1
238: formats_last=
239:
240: while true; do
241:
242: # dispatch on the radix to get the largest factor we will
243: # use, its exponent, and a coarse upper bound on this
244: # value's exponent in the worst-case radix of two:
245: #
246: case ${radix} in
247: 2) exponent_radix2=${exponent} ; x=16777216 ; exponent_x=24 ;;
248: 10) exponent_radix2=`expr ${exponent} \* 4` ; x=10000 ; exponent_x=4 ;;
249: *)
250: echo "$PROG internal error: can't handle radix ${radix}" 1>&2
251: exit 1
252: ;;
253: esac
254:
255: # we assume that all floating-point formats that use a
256: # radix of two support at least positive and negative
257: # exponents of magnitude 16. if this exponent's
258: # magnitude is greater than that, dispatch to get the
259: # list of floating-point formats that support it:
260: #
261: formats=
262: if test `expr ${exponent_radix2} \> 16` != 0; then
263:
264: # the IEEE 754 types:
265: #
266: if test `expr ${exponent_radix2} \< 16384` != 0; then
267: formats="${formats} | TME_FLOAT_FORMAT_IEEE754_EXTENDED80"
268: fi
269: if test `expr ${exponent_radix2} \< 1024` != 0; then
270: formats="${formats} | TME_FLOAT_FORMAT_IEEE754_DOUBLE"
271: fi
272: if test `expr ${exponent_radix2} \< 128` != 0; then
273: formats="${formats} | TME_FLOAT_FORMAT_IEEE754_SINGLE"
274: fi
275:
276: # if we don't know any formats that support this
277: # exponent, stop now:
278: #
279: if test "x${formats}" = x; then
280: break
281: fi
282:
283: # clean up the formats:
284: #
285: formats="((TME_FLOAT_FORMAT_${_BUILTIN_TYPE} & ("`echo "${formats}" | sed -e 's%^ | %%'`")) != 0)"
286: fi
287:
288: # if the formats have changed:
289: #
290: if test "x${formats}" != "x${formats_last}"; then
291:
292: # close any old #if first:
293: #
294: if test "x${formats_last}" != x; then
295: echo ""
296: echo "#endif /* ${formats_last} */"
297: fi
298:
299: # open the new #if:
300: #
301: echo ""
302: echo "#if ${formats}"
303: formats_last=${formats}
304: fi
305:
306: # compute this value:
307: #
308: echo ""
309: echo " /* ${radix}^${sign}${exponent}: */"
310: exponent_remaining=${exponent}
311: value=1
312: while test ${exponent_remaining} != 0; do
313: if test `expr ${exponent_remaining} \>= ${exponent_x}` = 1; then
314: value="(${value} ${combine} ((${builtin_type}) ((tme_uint32_t) ${x})))"
315: exponent_remaining=`expr ${exponent_remaining} - ${exponent_x}`
316: else
317: x=`expr ${x} / ${radix}`
318: exponent_x=`expr ${exponent_x} - 1`
319: fi
320: done
321: echo " ${value},"
322:
323: # double the exponent:
324: #
325: exponent=`expr ${exponent} \* 2`
326: done
327:
328: # close any #if:
329: #
330: if test "x${formats_last}" != x; then
331: echo ""
332: echo "#endif /* ${formats_last} */"
333: fi
334:
335: echo "};"
336: done
337:
338: cat <<EOF
339:
340: /* this returns the radix ${radix} mantissa and exponent of an in-range ${builtin_type}.
341: the mantissa is either zero, or in the range [1,${radix}): */
342: ${builtin_type}
343: tme_float_radix${radix}_mantissa_exponent_${_builtin_type}(${builtin_type} value, tme_int32_t *_exponent)
344: {
345: tme_int32_t exponent;
346: tme_uint32_t exponent_bit;
347: int negate;
348:
349: /* start with an exponent of zero: */
350: exponent = 0;
351:
1.1.1.2 ! root 352: /* if the value is positive or negative zero, return the value: */
! 353: if (value == 0.0
! 354: || -value == 0.0) {
1.1 root 355: *_exponent = exponent;
1.1.1.2 ! root 356: return (value);
! 357: }
! 358:
! 359: /* take the magnitude of the value, but remember if it was negative: */
! 360: negate = (value < 0);
! 361: if (negate) {
! 362: value = 0 - value;
1.1 root 363: }
364:
365: /* while the value is less than one: */
366: exponent_bit = TME_ARRAY_ELS(_tme_float_radix${radix}_exponent_bits_${_builtin_type}_neg) - 1;
367: for (; value < 1; ) {
368:
369: /* if value is less than or equal to ${radix}^-(2^exponent_bit),
370: divide value by ${radix}^-(2^exponent_bit), and subtract 2^exponent_bit
371: from exponent: */
372: if (value <= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_neg[exponent_bit]
373: || exponent_bit == 0) {
374: value /= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_neg[exponent_bit];
375: exponent -= (1 << exponent_bit);
376: }
377:
378: /* otherwise, move to the next exponent bit: */
379: else {
380: exponent_bit--;
381: }
382: }
383:
1.1.1.2 ! root 384: /* while the value is greater than or equal to ${radix}: */
1.1 root 385: exponent_bit = TME_ARRAY_ELS(_tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos) - 1;
1.1.1.2 ! root 386: for (; value >= ${radix}; ) {
1.1 root 387:
388: /* if value is greater than or equal to ${radix}^(2^exponent_bit),
389: divide value by ${radix}^(2^exponent_bit), and add 2^exponent_bit
390: to exponent: */
391: if (value >= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos[exponent_bit]
392: || exponent_bit == 0) {
393: value /= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos[exponent_bit];
394: exponent += (1 << exponent_bit);
395: }
396:
397: /* otherwise, move to the next exponent bit: */
398: else {
399: exponent_bit--;
400: }
401: }
402:
403: /* done: */
404: *_exponent = exponent;
405: return (negate ? 0 - value : value);
406: }
407:
408: /* this scales a value by adding n to its exponent: */
409: ${builtin_type}
410: tme_float_radix${radix}_scale_${_builtin_type}(${builtin_type} value, tme_int32_t _n)
411: {
412: tme_uint32_t exponent_bit, exponent;
413: tme_uint32_t n;
414:
415: /* start with the most significant exponent bit: */
416: exponent_bit = TME_ARRAY_ELS(_tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos) - 1;
417: exponent = (1 << exponent_bit);
418:
419: /* if n is negative: */
420: if (_n < 0) {
421:
422: for (n = 0 - _n; n > 0;) {
423: if (n >= exponent || exponent == 1) {
424: value /= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos[exponent_bit];
425: n -= exponent;
426: }
427: else {
428: exponent >>= 1;
429: exponent_bit--;
430: }
431: }
432: }
433:
434: /* otherwise, n is positive: */
435: else {
436: for (n = _n; n > 0;) {
437: if (n >= exponent || exponent == 1) {
438: value *= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos[exponent_bit];
439: n -= exponent;
440: }
441: else {
442: exponent >>= 1;
443: exponent_bit--;
444: }
445: }
446: }
447:
448: return (value);
449: }
450: EOF
451: done
452:
453: # dispatch on the type to close any protection:
454: #
455: case ${_builtin_type} in
456: long_double)
457: echo ; echo "#endif /* _TME_HAVE_${_BUILTIN_TYPE} */" ;;
458: *) ;;
459: esac
460:
461: done
462:
463: # done:
464: #
465: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.