Subversion Repositories HelenOS

Rev

Rev 734 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2005 Josef Cejka
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #include "sftypes.h"
  30. #include "sub.h"
  31.  
  32. /** Subtract two float32 numbers with same signs
  33.  */
  34. float32 subFloat32(float32 a, float32 b)
  35. {
  36.     int expdiff;
  37.     __u32 exp1,exp2,mant1,mant2;
  38.     float32 result;
  39.  
  40.     result.f = 0;
  41.    
  42.     expdiff=a.parts.exp - b.parts.exp;
  43.     if ((expdiff<0)||((expdiff==0)&&(a.parts.mantisa<b.parts.mantisa))) {
  44.         if (isFloat32NaN(b)) {
  45.             //TODO: fix SigNaN
  46.             if (isFloat32SigNaN(b)) {
  47.             };
  48.             return b;
  49.         };
  50.        
  51.         if (b.parts.exp==0xFF) {
  52.             b.parts.sign=!b.parts.sign; /* num -(+-inf) = -+inf */
  53.             return b;
  54.         }
  55.        
  56.         result.parts.sign = !a.parts.sign;
  57.        
  58.         mant1=b.parts.mantisa;
  59.         exp1=b.parts.exp;
  60.         mant2=a.parts.mantisa;
  61.         exp2=a.parts.exp;
  62.         expdiff*=-1;
  63.     } else {
  64.         if (isFloat32NaN(a)) {
  65.             //TODO: fix SigNaN
  66.             if ((isFloat32SigNaN(a))||(isFloat32SigNaN(b))) {
  67.             };
  68.             return a;
  69.         };
  70.        
  71.         if (a.parts.exp==0xFF) {
  72.             if (b.parts.exp==0xFF) {
  73.                 /* inf - inf => nan */
  74.                 //TODO: fix exception
  75.                 result.binary = FLOAT32_NAN;
  76.                 return result;
  77.             };
  78.             return a;
  79.         }
  80.        
  81.         result.parts.sign = a.parts.sign;
  82.        
  83.         mant1=a.parts.mantisa;
  84.         exp1=a.parts.exp;
  85.         mant2=b.parts.mantisa;
  86.         exp2=b.parts.exp;  
  87.     };
  88.    
  89.     if (exp1==0) {
  90.         //both are denormalized
  91.         result.parts.mantisa=mant1-mant2;
  92.         if (result.parts.mantisa>mant1) {
  93.             //TODO: underflow exception
  94.             return result;
  95.         };
  96.         result.parts.exp=0;
  97.         return result;
  98.     };
  99.    
  100.     // create some space for rounding
  101.     mant1<<=6;
  102.     mant2<<=6;
  103.    
  104.     mant1|=0x20000000; //add hidden bit
  105.    
  106.    
  107.     if (exp2==0) {
  108.         --expdiff; 
  109.     } else {
  110.         mant2|=0x20000000; //hidden bit
  111.     };
  112.    
  113.     if (expdiff>24) {
  114.          goto done;
  115.          };
  116.    
  117.     mant1 = mant1-(mant2>>expdiff);
  118. done:
  119.     //TODO: find first nonzero digit and shift result and detect possibly underflow
  120.     while ((exp1>0)&&(!(mant1&0x20000000))) {
  121.         exp1--;
  122.         mant1 <<= 1;
  123.             /* TODO: fix underflow - mant1 == 0 does not necessary means underflow... */
  124.     };
  125.    
  126.     //rounding - if first bit after mantisa is set then round up   
  127.     mant1 += 0x20;
  128.  
  129.     if (mant1&0x40000000) {
  130.         ++exp1;
  131.         mant1>>=1;
  132.     };
  133.    
  134.     result.parts.mantisa = ((mant1&(~0x20000000))>>6); /*Clear hidden bit and shift */
  135.     result.parts.exp = exp1;
  136.    
  137.     return result;
  138. };
  139.  
  140.