Changeset 816


Ignore:
Timestamp:
Apr 28, 2016, 1:12:20 PM (9 years ago)
Author:
cfuguet
Message:

Add a software integer version of the libmath/sqrt function.

Also a flag to enable/disable the use of hard FPU instructions is
add into the giet_config.h file.

Location:
soft/giet_vm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_config.h

    r791 r816  
    6161#define GIET_SDC_PERIOD           2            /* number of cycles in SDC period */
    6262#define GIET_SR_INIT_VALUE        0x2000FF13   /* SR initial value (before eret) */
     63#define GIET_USE_HARD_FLOAT       0            /* hard float supported */
    6364
    6465#endif
  • soft/giet_vm/giet_libs/math/sqrt.c

    r581 r816  
     1#include "../math.h"
     2#include "math_private.h"
     3
     4static const double one = 1.0, tiny = 1.0e-300;
     5
     6/* this function was taken from the uCLibc library
     7 * Return correctly rounded sqrt.
     8 * Method:
     9 *   Bit by bit method using integer arithmetic. (Slow, but portable)
     10 *   1. Normalization
     11 *      Scale x to y in [1,4) with even powers of 2:
     12 *      find an integer k such that  1 <= (y=x*2^(2k)) < 4, then
     13 *              sqrt(x) = 2^k * sqrt(y)
     14 *   2. Bit by bit computation
     15 *      Let q  = sqrt(y) truncated to i bit after binary point (q = 1),
     16 *           i                                                   0
     17 *                                     i+1         2
     18 *          s  = 2*q , and      y  =  2   * ( y - q  ).         (1)
     19 *           i      i            i                 i
     20 *
     21 *      To compute q    from q , one checks whether
     22 *                  i+1       i
     23 *
     24 *                            -(i+1) 2
     25 *                      (q + 2      ) <= y.                     (2)
     26 *                        i
     27 *                                                            -(i+1)
     28 *      If (2) is false, then q   = q ; otherwise q   = q  + 2      .
     29 *                             i+1   i             i+1   i
     30 *
     31 *      With some algebric manipulation, it is not difficult to see
     32 *      that (2) is equivalent to
     33 *                             -(i+1)
     34 *                      s  +  2       <= y                      (3)
     35 *                       i                i
     36 *
     37 *      The advantage of (3) is that s  and y  can be computed by
     38 *                                    i      i
     39 *      the following recurrence formula:
     40 *          if (3) is false
     41 *
     42 *          s     =  s  ,       y    = y   ;                    (4)
     43 *           i+1      i          i+1    i
     44 *
     45 *          otherwise,
     46 *                         -i                     -(i+1)
     47 *          s     =  s  + 2  ,  y    = y  -  s  - 2             (5)
     48 *           i+1      i          i+1    i     i
     49 *
     50 *      One may easily use induction to prove (4) and (5).
     51 *      Note. Since the left hand side of (3) contain only i+2 bits,
     52 *            it does not necessary to do a full (53-bit) comparison
     53 *            in (3).
     54 *   3. Final rounding
     55 *      After generating the 53 bits result, we compute one more bit.
     56 *      Together with the remainder, we can decide whether the
     57 *      result is exact, bigger than 1/2ulp, or less than 1/2ulp
     58 *      (it will never equal to 1/2ulp).
     59 *      The rounding mode can be detected by checking whether
     60 *      huge + tiny is equal to huge, and whether huge - tiny is
     61 *      equal to huge for some floating point number "huge" and "tiny".
     62 *
     63 * Special cases:
     64 *      sqrt(+-0) = +-0         ... exact
     65 *      sqrt(inf) = inf
     66 *      sqrt(-ve) = NaN         ... with invalid signal
     67 *      sqrt(NaN) = NaN         ... with invalid signal for signaling NaN
     68 *
     69 * Other methods : see the appended file at the end of the program below.
     70 *---------------
     71 */
     72static double __ieee754_sqrt(double x)
     73{
     74    double z;
     75    int32_t sign = (int)0x80000000;
     76    int32_t ix0,s0,q,m,t,i;
     77    uint32_t r,t1,s1,ix1,q1;
     78
     79    EXTRACT_WORDS(ix0,ix1,x);
     80
     81    /* take care of Inf and NaN */
     82    if((ix0&0x7ff00000)==0x7ff00000) {
     83        return x*x+x;           /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
     84                               sqrt(-inf)=sNaN */
     85    }
     86    /* take care of zero */
     87    if(ix0<=0) {
     88        if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
     89        else if(ix0<0)
     90            return (x-x)/(x-x);         /* sqrt(-ve) = sNaN */
     91    }
     92    /* normalize x */
     93    m = (ix0>>20);
     94    if(m==0) {                          /* subnormal x */
     95        while(ix0==0) {
     96            m -= 21;
     97            ix0 |= (ix1>>11); ix1 <<= 21;
     98        }
     99        for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
     100        m -= i-1;
     101        ix0 |= (ix1>>(32-i));
     102        ix1 <<= i;
     103    }
     104    m -= 1023;  /* unbias exponent */
     105    ix0 = (ix0&0x000fffff)|0x00100000;
     106    if(m&1){    /* odd m, double x to make it even */
     107        ix0 += ix0 + ((ix1&sign)>>31);
     108        ix1 += ix1;
     109    }
     110    m >>= 1;    /* m = [m/2] */
     111
     112    /* generate sqrt(x) bit by bit */
     113    ix0 += ix0 + ((ix1&sign)>>31);
     114    ix1 += ix1;
     115    q = q1 = s0 = s1 = 0;       /* [q,q1] = sqrt(x) */
     116    r = 0x00200000;             /* r = moving bit from right to left */
     117
     118    while(r!=0) {
     119        t = s0+r;
     120        if(t<=ix0) {
     121            s0   = t+r;
     122            ix0 -= t;
     123            q   += r;
     124        }
     125        ix0 += ix0 + ((ix1&sign)>>31);
     126        ix1 += ix1;
     127        r>>=1;
     128    }
     129
     130    r = sign;
     131    while(r!=0) {
     132        t1 = s1+r;
     133        t  = s0;
     134        if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
     135            s1  = t1+r;
     136            if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
     137            ix0 -= t;
     138            if (ix1 < t1) ix0 -= 1;
     139            ix1 -= t1;
     140            q1  += r;
     141        }
     142        ix0 += ix0 + ((ix1&sign)>>31);
     143        ix1 += ix1;
     144        r>>=1;
     145    }
     146
     147    /* use floating add to find out rounding direction */
     148    if((ix0|ix1)!=0) {
     149        z = one-tiny; /* trigger inexact flag */
     150        if (z>=one) {
     151            z = one+tiny;
     152            if (q1==(uint32_t)0xffffffff) { q1=0; q += 1;}
     153            else if (z>one) {
     154                if (q1==(uint32_t)0xfffffffe) q+=1;
     155                q1+=2;
     156            } else
     157                q1 += (q1&1);
     158        }
     159    }
     160    ix0 = (q>>1)+0x3fe00000;
     161    ix1 =  q1>>1;
     162    if ((q&1)==1) ix1 |= sign;
     163    ix0 += (m <<20);
     164    INSERT_WORDS(z,ix0,ix1);
     165    return z;
     166}
    1167
    2168double sqrt(double x)
    3169{
    4   double z;
    5   __asm__ ("sqrt.d %0,%1" : "=f" (z) : "f" (x));
    6   return z;
     170#if GIET_USE_HARD_FLOAT
     171    double z;
     172    __asm__ ("sqrt.d %0,%1" : "=f" (z) : "f" (x));
     173    return z;
     174#else
     175    return __ieee754_sqrt(x);
     176#endif
    7177}
    8178
     179/*
     180 * vim: ts=4 : sts=4 : sw=4 : et
     181 */
Note: See TracChangeset for help on using the changeset viewer.