compact.c

Go to the documentation of this file.
00001 /*
00002   (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
00003   See the copyright notice in the ACK home directory, in the file "Copyright".
00004 */
00005 
00006 /* $Header: /opt/proj/minix/cvsroot/src/lib/float/compact.c,v 1.1.1.1 2005/04/21 14:56:10 beng Exp $ */
00007 
00008 /*
00009         COMPACT EXTEND FORMAT INTO FLOAT OF PROPER SIZE
00010 */
00011 
00012 # include "FP_bias.h"
00013 # include "FP_shift.h"
00014 # include "FP_trap.h"
00015 # include "FP_types.h"
00016 # include "get_put.h"
00017 
00018 void
00019 compact(f,to,size)
00020 EXTEND  *f;
00021 unsigned long   *to;
00022 int     size;
00023 {
00024         int     error = 0;
00025 
00026         if (size == sizeof(DOUBLE)) {
00027         /*
00028          * COMPACT EXTENDED INTO DOUBLE
00029          */
00030                 DOUBLE *DBL = (DOUBLE *) (void *) to;
00031 
00032                 if ((f->m1|(f->m2 & DBL_ZERO)) == 0L)   {
00033                         zrf8(DBL);
00034                         return;
00035                 }
00036                 f->exp += DBL_BIAS;     /* restore proper bias  */
00037                 if (f->exp > DBL_MAX)   {
00038 dbl_over:                       trap(EFOVFL);
00039                         f->exp = DBL_MAX+1;
00040                         f->m1 = 0;
00041                         f->m2 = 0;
00042                         if (error++)
00043                                 return;
00044                 }
00045                 else if (f->exp < DBL_MIN)      {
00046                         b64_rsft(&(f->mantissa));
00047                         if (f->exp < 0) {
00048                                 b64_sft(&(f->mantissa), -f->exp);
00049                                 f->exp = 0;
00050                         }
00051                         /* underflow ??? */
00052                 }
00053                         
00054                 /* local CAST conversion                */
00055 
00056                 /* because of special format shift only 10 bits */
00057                 /* bit shift mantissa 10 bits           */
00058 
00059                 /* first align within words, then do store operation */
00060 
00061                 DBL->d[0] = f->m1 >> DBL_RUNPACK;   /* plus 22 == 32 */
00062                 DBL->d[1] = f->m2 >> DBL_RUNPACK;   /* plus 22 == 32 */
00063                 DBL->d[1] |= (f->m1 << DBL_LUNPACK); /* plus 10 == 32 */
00064 
00065                 /* if not exact then round to nearest   */
00066                 /* on a tie, round to even */
00067 
00068 #ifdef EXCEPTION_INEXACT
00069                 if ((f->m2 & DBL_EXACT) != 0) {
00070                     INEXACT();
00071 #endif
00072                     if (((f->m2 & DBL_EXACT) > DBL_ROUNDUP)
00073                         || ((f->m2 & DBL_EXACT) == DBL_ROUNDUP
00074                             && (f->m2 & (DBL_ROUNDUP << 1)))) {
00075                         DBL->d[1]++;    /* rounding up  */
00076                         if (DBL->d[1] == 0L) { /* carry out     */
00077                             DBL->d[0]++;
00078 
00079                             if (f->exp == 0 && (DBL->d[0] & ~DBL_MASK)) {
00080                                         f->exp++;
00081                                 }
00082                             if (DBL->d[0] & DBL_CARRYOUT) { /* carry out */
00083                                 if (DBL->d[0] & 01)
00084                                     DBL->d[1] = CARRYBIT;
00085                                 DBL->d[0] >>= 1;
00086                                 f->exp++;
00087                             }
00088                         }
00089                         /*      check for overflow                      */
00090                         if (f->exp > DBL_MAX)
00091                                 goto dbl_over;
00092                     }
00093 #ifdef EXCEPTION_INEXACT
00094                 }
00095 #endif
00096 
00097                 /*
00098                  * STORE EXPONENT AND SIGN:
00099                  *
00100                  * 1) clear leading bits (B4-B15)
00101                  * 2) shift and store exponent
00102                  */
00103 
00104                 DBL->d[0] &= DBL_MASK;
00105                 DBL->d[0] |= 
00106                         ((long) (f->exp << DBL_EXPSHIFT) << EXP_STORE);
00107                 if (f->sign)
00108                         DBL->d[0] |= CARRYBIT;
00109 
00110                 /*
00111                  * STORE MANTISSA
00112                  */
00113 
00114 #if FL_MSL_AT_LOW_ADDRESS
00115                 put4(DBL->d[0], (char *) &DBL->d[0]);
00116                 put4(DBL->d[1], (char *) &DBL->d[1]);
00117 #else
00118                 { unsigned long l;
00119                   put4(DBL->d[1], (char *) &l);
00120                   put4(DBL->d[0], (char *) &DBL->d[1]);
00121                   DBL->d[0] = l;
00122                 }
00123 #endif
00124         }
00125         else {
00126                 /*
00127                  * COMPACT EXTENDED INTO FLOAT
00128                  */
00129                 SINGLE  *SGL;
00130 
00131                 /* local CAST conversion                */
00132                 SGL = (SINGLE *) (void *) to;
00133                 if ((f->m1 & SGL_ZERO) == 0L)   {
00134                         *SGL = 0L;
00135                         return;
00136                 }
00137                 f->exp += SGL_BIAS;     /* restore bias */
00138                 if (f->exp > SGL_MAX)   {
00139 sgl_over:                       trap(EFOVFL);
00140                         f->exp = SGL_MAX+1;
00141                         f->m1 = 0L;
00142                         f->m2 = 0L;
00143                         if (error++)
00144                                 return;
00145                 }
00146                 else if (f->exp < SGL_MIN)      {
00147                         b64_rsft(&(f->mantissa));
00148                         if (f->exp < 0) {
00149                                 b64_sft(&(f->mantissa), -f->exp);
00150                                 f->exp = 0;
00151                         }
00152                         /* underflow ??? */
00153                 }
00154 
00155                 /* shift mantissa and store     */
00156                 *SGL = (f->m1 >> SGL_RUNPACK);
00157 
00158                 /* check for rounding to nearest        */
00159                 /* on a tie, round to even              */
00160 #ifdef EXCEPTION_INEXACT
00161                 if (f->m2 != 0 ||
00162                     (f->m1 & SGL_EXACT) != 0L) {
00163                         INEXACT();
00164 #endif
00165                         if (((f->m1 & SGL_EXACT) > SGL_ROUNDUP)
00166                             || ((f->m1 & SGL_EXACT) == SGL_ROUNDUP
00167                                 && (f->m1 & (SGL_ROUNDUP << 1)))) {
00168                                 (*SGL)++;
00169                                 if (f->exp == 0 && (*SGL & ~SGL_MASK)) {
00170                                         f->exp++;
00171                                 }
00172                         /* check normal */
00173                                 if (*SGL & SGL_CARRYOUT)        {
00174                                         *SGL >>= 1;
00175                                         f->exp++;
00176                                 }
00177                                 if (f->exp > SGL_MAX)
00178                                         goto sgl_over;
00179                         }
00180 #ifdef EXCEPTION_INEXACT
00181                 }
00182 #endif
00183 
00184                 /*
00185                  * STORE EXPONENT AND SIGN:
00186                  *
00187                  * 1) clear leading bit of fraction
00188                  * 2) shift and store exponent
00189                  */
00190 
00191                 *SGL &= SGL_MASK; /* B23-B31 are 0 */
00192                 *SGL |= ((long) (f->exp << SGL_EXPSHIFT) << EXP_STORE);
00193                 if (f->sign)
00194                         *SGL |= CARRYBIT;
00195 
00196                 /*
00197                  * STORE MANTISSA
00198                  */
00199 
00200                 put4(*SGL, (char *) &SGL);
00201         }
00202 }

Generated on Fri Apr 14 22:57:26 2006 for minix by  doxygen 1.4.6