Beispiel #1
0
void scs_log(scs_ptr res, db_number y, int E) {
    scs_t R, sc_ln2_times_E, res1, addi;
    scs_ptr ti, inv_wi;
    db_number z, wi;
    int i;


#if EVAL_PERF
    crlibm_second_step_taken++;
#endif


    /* to normalize y.d and round to nearest      */
    /* + (1-trunc(sqrt(2.)/2 * 2^(4))*2^(-4) )+2.^(-(4+1))*/
    z.d = y.d + norm_number.d;
    i = (z.i[HI_ENDIAN] & 0x000fffff);
    i = i >> 16; /* 0<= i <=11 */


    wi.d = ((double)(11+i))*0.0625;

    /* (1+f-w_i) */
    y.d -= wi.d;

    /* Table reduction */
    ti     = table_ti_ptr[i];
    inv_wi = table_inv_wi_ptr[i];

    /* R = (1+f-w_i)/w_i */
    scs_set_d(R, y.d);
    scs_mul(R, R, inv_wi);


    /*
     * Polynomial evaluation of log(1 + R) with an error less than 2^(-130)
     */

    scs_mul(res1, constant_poly_ptr[0], R);
    for(i=1; i<20; i++) {
        scs_add(addi, constant_poly_ptr[i], res1);
        scs_mul(res1, addi, R);
    }

    if(E==0) {
        scs_add(res, res1, ti);
    } else {
        /* sc_ln2_times_E = E*log(2)  */
        scs_set(sc_ln2_times_E, sc_ln2_ptr);

        if (E >= 0) {
            scs_mul_ui(sc_ln2_times_E, (unsigned int) E);
        } else {
            scs_mul_ui(sc_ln2_times_E, (unsigned int) -E);
            sc_ln2_times_E->sign = -1;
        }
        scs_add(addi, res1, ti);
        scs_add(res, addi, sc_ln2_times_E);
    }
}
Beispiel #2
0
/*************************************************************
 *************************************************************
 *               ROUNDED  TO NEAREST
 *************************************************************
 *************************************************************/
double log10_rn(double x)
{
  scs_t R, res1;
  scs_t sc_ln2_r10_times_E;
  scs_ptr inv_wi, ti;
 
  db_number nb, nb2, wi, resd;
  int i, E=0;

  nb.d = x;
  /* Filter cases */
  if (nb.i[HI_ENDIAN] < 0x00100000){        /* x < 2^(-1022)    */
    if (((nb.i[HI_ENDIAN] & 0x7fffffff)|nb.i[LO_ENDIAN])==0)
      /* return 1.0/0.0; */                       /* log(+/-0) = -Inf */
	 return NInf.d;
    if (nb.i[HI_ENDIAN] < 0) 
      /* return (x-x)/0; */                       /* log(-x) = Nan    */
	 return NaN.d;

    /* Subnormal number */
    E    -= (SCS_NB_BITS*2); /* keep in mind that x is a subnormal number */ 
    nb.d *=SCS_RADIX_TWO_DOUBLE;  /* make x as normal number     */         
    /* We may just want add 2 to the scs number.index */
    /* may be .... we will see */
  }
  if (nb.i[HI_ENDIAN] >= 0x7ff00000)
    return x+x;                             /* Inf or Nan       */

  /* find n, nb.d such that sqrt(2)/2 < nb.d < sqrt(2) */
  E += (nb.i[HI_ENDIAN]>>20)-1023;
  nb.i[HI_ENDIAN] =  (nb.i[HI_ENDIAN] & 0x000fffff) | 0x3ff00000;
  if (nb.d > SQRT_2){
    nb.d *= 0.5;
    E++;
  }


  /* to normalize nb.d and round to nearest      */
  /* +((2^4 - trunc(sqrt(2)/2) *2^4 )*2 + 1)/2^5 */ 
  nb2.d = nb.d + norm_number.d; 
  i = (nb2.i[HI_ENDIAN] & 0x000fffff);
  i = i >> 16; /* 0<= i <=11 */
  
  wi.d = (11+i)*(double)0.6250e-1;

  /* (1+f-w_i) */
  nb.d -= wi.d; 
  
  /* Table reduction */
  ti     = table_ti_ptr[i]; 
  inv_wi = table_inv_wi_ptr[i];

 
  /* R = (1+f-w_i)/w_i */
  scs_set_d(R, nb.d);
  scs_mul(R, R, inv_wi);
 

  /* sc_ln2_r10_times_E = E*log10(2)  */
  scs_set(sc_ln2_r10_times_E, sc_ln2_r10_ptr);
  
  if (E >= 0){
    scs_mul_ui(sc_ln2_r10_times_E, (unsigned int) E);
  }else{
    scs_mul_ui(sc_ln2_r10_times_E, (unsigned int) -E);
    sc_ln2_r10_times_E->sign = -1;
  }


  /*
   * Polynomial evaluation of log10(1 + R) with an error less than 2^(-130)
   */
  scs_mul(res1, constant_poly_ptr[0], R);
  for(i=1; i<20; i++){
    scs_add(res1, constant_poly_ptr[i], res1);
    scs_mul(res1, res1, R);
  }
  scs_add(res1, res1, ti);
  scs_add(res1, res1, sc_ln2_r10_times_E);  


  scs_get_d(&resd.d, res1);  
  
  return resd.d;
}