|
|
1.1 root 1: #! /bin/sh
2:
3: # $Id: float-auto.sh,v 1.1 2005/02/17 12:17:00 fredette Exp $
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>
55: _TME_RCSID("\$Id: float-auto.sh,v 1.1 2005/02/17 12:17:00 fredette Exp $");
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:
80: # permute over the radices:
81: #
82: for radix in 2 10; do
83:
84: # if we're generating a header:
85: #
86: if $header; then
87: cat <<EOF
88:
89: /* this returns the radix ${radix} mantissa and exponent of an in-range ${builtin_type}.
90: the mantissa is either zero, or in the range [1,${radix}): */
91: ${builtin_type} tme_float_radix${radix}_mantissa_exponent_${_builtin_type} _TME_P((${builtin_type}, tme_int32_t *));
92:
93: /* this scales a value by adding n to its radix ${radix} exponent: */
94: ${builtin_type} tme_float_radix${radix}_scale_${_builtin_type} _TME_P((${builtin_type}, tme_int32_t));
95: EOF
96: continue
97: fi
98:
99: # permute over the sign of the exponent:
100: #
101: for _sign in pos neg; do
102:
103: # make the sign into two operators:
104: #
105: if test ${_sign} = pos; then sign= ; combine='*' ; else sign=- ; combine='/' ; fi
106:
107: echo ""
108: echo "/* a series of ${builtin_type} values of the form ${radix}^${sign}x, where x is a power of two: */"
109: echo "static const ${builtin_type} _tme_float_radix${radix}_exponent_bits_${_builtin_type}_${_sign}[] = {"
110: exponent=1
111: formats_last=
112:
113: while true; do
114:
115: # dispatch on the radix to get the largest factor we will
116: # use, its exponent, and a coarse upper bound on this
117: # value's exponent in the worst-case radix of two:
118: #
119: case ${radix} in
120: 2) exponent_radix2=${exponent} ; x=16777216 ; exponent_x=24 ;;
121: 10) exponent_radix2=`expr ${exponent} \* 4` ; x=10000 ; exponent_x=4 ;;
122: *)
123: echo "$PROG internal error: can't handle radix ${radix}" 1>&2
124: exit 1
125: ;;
126: esac
127:
128: # we assume that all floating-point formats that use a
129: # radix of two support at least positive and negative
130: # exponents of magnitude 16. if this exponent's
131: # magnitude is greater than that, dispatch to get the
132: # list of floating-point formats that support it:
133: #
134: formats=
135: if test `expr ${exponent_radix2} \> 16` != 0; then
136:
137: # the IEEE 754 types:
138: #
139: if test `expr ${exponent_radix2} \< 16384` != 0; then
140: formats="${formats} | TME_FLOAT_FORMAT_IEEE754_EXTENDED80"
141: fi
142: if test `expr ${exponent_radix2} \< 1024` != 0; then
143: formats="${formats} | TME_FLOAT_FORMAT_IEEE754_DOUBLE"
144: fi
145: if test `expr ${exponent_radix2} \< 128` != 0; then
146: formats="${formats} | TME_FLOAT_FORMAT_IEEE754_SINGLE"
147: fi
148:
149: # if we don't know any formats that support this
150: # exponent, stop now:
151: #
152: if test "x${formats}" = x; then
153: break
154: fi
155:
156: # clean up the formats:
157: #
158: formats="((TME_FLOAT_FORMAT_${_BUILTIN_TYPE} & ("`echo "${formats}" | sed -e 's%^ | %%'`")) != 0)"
159: fi
160:
161: # if the formats have changed:
162: #
163: if test "x${formats}" != "x${formats_last}"; then
164:
165: # close any old #if first:
166: #
167: if test "x${formats_last}" != x; then
168: echo ""
169: echo "#endif /* ${formats_last} */"
170: fi
171:
172: # open the new #if:
173: #
174: echo ""
175: echo "#if ${formats}"
176: formats_last=${formats}
177: fi
178:
179: # compute this value:
180: #
181: echo ""
182: echo " /* ${radix}^${sign}${exponent}: */"
183: exponent_remaining=${exponent}
184: value=1
185: while test ${exponent_remaining} != 0; do
186: if test `expr ${exponent_remaining} \>= ${exponent_x}` = 1; then
187: value="(${value} ${combine} ((${builtin_type}) ((tme_uint32_t) ${x})))"
188: exponent_remaining=`expr ${exponent_remaining} - ${exponent_x}`
189: else
190: x=`expr ${x} / ${radix}`
191: exponent_x=`expr ${exponent_x} - 1`
192: fi
193: done
194: echo " ${value},"
195:
196: # double the exponent:
197: #
198: exponent=`expr ${exponent} \* 2`
199: done
200:
201: # close any #if:
202: #
203: if test "x${formats_last}" != x; then
204: echo ""
205: echo "#endif /* ${formats_last} */"
206: fi
207:
208: echo "};"
209: done
210:
211: cat <<EOF
212:
213: /* this returns the radix ${radix} mantissa and exponent of an in-range ${builtin_type}.
214: the mantissa is either zero, or in the range [1,${radix}): */
215: ${builtin_type}
216: tme_float_radix${radix}_mantissa_exponent_${_builtin_type}(${builtin_type} value, tme_int32_t *_exponent)
217: {
218: tme_int32_t exponent;
219: tme_uint32_t exponent_bit;
220: int negate;
221:
222: /* take the magnitude of the value, but remember if it was negative: */
223: negate = (value < 0);
224: if (negate) {
225: value = 0 - value;
226: }
227:
228: /* start with an exponent of zero: */
229: exponent = 0;
230:
231: /* if the value is zero, return zero: */
232: /* XXX FIXME this returns positive zero for a negative zero argument: */
233: if (value == 0) {
234: *_exponent = exponent;
235: return (0);
236: }
237:
238: /* while the value is less than one: */
239: exponent_bit = TME_ARRAY_ELS(_tme_float_radix${radix}_exponent_bits_${_builtin_type}_neg) - 1;
240: for (; value < 1; ) {
241:
242: /* if value is less than or equal to ${radix}^-(2^exponent_bit),
243: divide value by ${radix}^-(2^exponent_bit), and subtract 2^exponent_bit
244: from exponent: */
245: if (value <= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_neg[exponent_bit]
246: || exponent_bit == 0) {
247: value /= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_neg[exponent_bit];
248: exponent -= (1 << exponent_bit);
249: }
250:
251: /* otherwise, move to the next exponent bit: */
252: else {
253: exponent_bit--;
254: }
255: }
256:
257: /* while the value is greater than ${radix}: */
258: exponent_bit = TME_ARRAY_ELS(_tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos) - 1;
259: for (; value > ${radix}; ) {
260:
261: /* if value is greater than or equal to ${radix}^(2^exponent_bit),
262: divide value by ${radix}^(2^exponent_bit), and add 2^exponent_bit
263: to exponent: */
264: if (value >= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos[exponent_bit]
265: || exponent_bit == 0) {
266: value /= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos[exponent_bit];
267: exponent += (1 << exponent_bit);
268: }
269:
270: /* otherwise, move to the next exponent bit: */
271: else {
272: exponent_bit--;
273: }
274: }
275:
276: /* done: */
277: *_exponent = exponent;
278: return (negate ? 0 - value : value);
279: }
280:
281: /* this scales a value by adding n to its exponent: */
282: ${builtin_type}
283: tme_float_radix${radix}_scale_${_builtin_type}(${builtin_type} value, tme_int32_t _n)
284: {
285: tme_uint32_t exponent_bit, exponent;
286: tme_uint32_t n;
287:
288: /* start with the most significant exponent bit: */
289: exponent_bit = TME_ARRAY_ELS(_tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos) - 1;
290: exponent = (1 << exponent_bit);
291:
292: /* if n is negative: */
293: if (_n < 0) {
294:
295: for (n = 0 - _n; n > 0;) {
296: if (n >= exponent || exponent == 1) {
297: value /= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos[exponent_bit];
298: n -= exponent;
299: }
300: else {
301: exponent >>= 1;
302: exponent_bit--;
303: }
304: }
305: }
306:
307: /* otherwise, n is positive: */
308: else {
309: for (n = _n; n > 0;) {
310: if (n >= exponent || exponent == 1) {
311: value *= _tme_float_radix${radix}_exponent_bits_${_builtin_type}_pos[exponent_bit];
312: n -= exponent;
313: }
314: else {
315: exponent >>= 1;
316: exponent_bit--;
317: }
318: }
319: }
320:
321: return (value);
322: }
323: EOF
324: done
325:
326: # dispatch on the type to close any protection:
327: #
328: case ${_builtin_type} in
329: long_double)
330: echo ; echo "#endif /* _TME_HAVE_${_BUILTIN_TYPE} */" ;;
331: *) ;;
332: esac
333:
334: done
335:
336: # done:
337: #
338: exit 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.