common.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 Josef Cejka
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include<sftypes.h>
00036 #include<common.h>
00037 
00038 /* Table for fast leading zeroes counting */
00039 char zeroTable[256] = {
00040         8, 7, 7, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, \
00041         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, \
00042         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
00043         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
00044         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
00045         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
00046         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
00047         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
00048         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
00049         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
00050         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
00051         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
00052         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
00053         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
00054         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
00055         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00056 };
00057 
00058 
00059 
00066 float64 finishFloat64(int32_t cexp, uint64_t cfrac, char sign)
00067 {
00068         float64 result;
00069 
00070         result.parts.sign = sign;
00071 
00072         /* find first nonzero digit and shift result and detect possibly underflow */
00073         while ((cexp > 0) && (cfrac) && (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1 ) )))) {
00074                 cexp--; 
00075                 cfrac <<= 1;
00076                         /* TODO: fix underflow */
00077         };
00078         
00079         if ((cexp < 0) || ( cexp == 0 && (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1)))))) {
00080                 /* FIXME: underflow */
00081                 result.parts.exp = 0;
00082                 if ((cexp + FLOAT64_FRACTION_SIZE + 1) < 0) { /* +1 is place for rounding */
00083                         result.parts.fraction = 0;
00084                         return result;
00085                 }
00086                 
00087                 while (cexp < 0) {
00088                         cexp++;
00089                         cfrac >>= 1;
00090                 }
00091         
00092                 cfrac += (0x1 << (64 - FLOAT64_FRACTION_SIZE - 3)); 
00093                 
00094                 if (!(cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1)))) {
00095                         
00096                         result.parts.fraction = ((cfrac >>(64 - FLOAT64_FRACTION_SIZE - 2) ) & (~FLOAT64_HIDDEN_BIT_MASK)); 
00097                         return result;
00098                 }       
00099         } else {
00100                 cfrac += (0x1 << (64 - FLOAT64_FRACTION_SIZE - 3)); 
00101         }
00102         
00103         ++cexp;
00104 
00105         if (cfrac & (FLOAT64_HIDDEN_BIT_MASK << (64 - FLOAT64_FRACTION_SIZE - 1 ))) {
00106                 ++cexp;
00107                 cfrac >>= 1;
00108         }       
00109 
00110         /* check overflow */
00111         if (cexp >= FLOAT64_MAX_EXPONENT ) {
00112                 /* FIXME: overflow, return infinity */
00113                 result.parts.exp = FLOAT64_MAX_EXPONENT;
00114                 result.parts.fraction = 0;
00115                 return result;
00116         }
00117 
00118         result.parts.exp = (uint32_t)cexp;
00119         
00120         result.parts.fraction = ((cfrac >>(64 - FLOAT64_FRACTION_SIZE - 2 ) ) & (~FLOAT64_HIDDEN_BIT_MASK)); 
00121         
00122         return result;  
00123 }
00124 
00128 int countZeroes64(uint64_t i)
00129 {
00130         int j;
00131         for (j =0; j < 64; j += 8) {
00132                 if ( i & (0xFFll << (56 - j))) {
00133                         return (j + countZeroes8(i >> (56 - j)));
00134                 }
00135         }
00136 
00137         return 64;
00138 }
00139 
00143 int countZeroes32(uint32_t i)
00144 {
00145         int j;
00146         for (j =0; j < 32; j += 8) {
00147                 if ( i & (0xFF << (24 - j))) {
00148                         return (j + countZeroes8(i >> (24 - j)));
00149                 }
00150         }
00151 
00152         return 32;
00153 }
00154 
00158 int countZeroes8(uint8_t i)
00159 {
00160         return zeroTable[i];
00161 }
00162 
00167 void roundFloat32(int32_t *exp, uint32_t *fraction)
00168 {
00169         /* rounding - if first bit after fraction is set then round up */
00170         (*fraction) += (0x1 << 6);
00171         
00172         if ((*fraction) & (FLOAT32_HIDDEN_BIT_MASK << 8)) { 
00173                 /* rounding overflow */
00174                 ++(*exp);
00175                 (*fraction) >>= 1;
00176         };
00177         
00178         if (((*exp) >= FLOAT32_MAX_EXPONENT ) || ((*exp) < 0)) {
00179                 /* overflow - set infinity as result */
00180                 (*exp) = FLOAT32_MAX_EXPONENT;
00181                 (*fraction) = 0;
00182                 return;
00183         }
00184 
00185         return;
00186 }
00187 
00192 void roundFloat64(int32_t *exp, uint64_t *fraction)
00193 {
00194         /* rounding - if first bit after fraction is set then round up */
00195         (*fraction) += (0x1 << 9);
00196         
00197         if ((*fraction) & (FLOAT64_HIDDEN_BIT_MASK << 11)) { 
00198                 /* rounding overflow */
00199                 ++(*exp);
00200                 (*fraction) >>= 1;
00201         };
00202         
00203         if (((*exp) >= FLOAT64_MAX_EXPONENT ) || ((*exp) < 0)) {
00204                 /* overflow - set infinity as result */
00205                 (*exp) = FLOAT64_MAX_EXPONENT;
00206                 (*fraction) = 0;
00207                 return;
00208         }
00209 
00210         return;
00211 }
00212 

Generated on Sun Jun 18 18:00:18 2006 for HelenOS Userspace (ia64) by  doxygen 1.4.6