Annotation of tme/generic/float-auto.sh, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.