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); } }
int rem_pio2_scs(scs_ptr result, const scs_ptr x){ uint64_t r[SCS_NB_WORDS+3], tmp; unsigned int N; /* result r[0],...,r[10] could store till 300 bits of precision */ /* that is really enough for computing the reduced argument */ int sign, i, j, ind; int *two_over_pi_pt; if ((X_EXP != 1)||(X_IND < -1)){ scs_set(result, x); return 0; } /* Compute the product |x| * 2/Pi */ if ((X_IND == -1)){ /* In this case we consider number between ]-1,+1[ */ /* we may use simpler algorithm such as Cody And Waite */ r[0] = 0; r[1] = 0; r[2] = (uint64_t)(two_over_pi[0]) * X_HW[0]; r[3] = ((uint64_t)(two_over_pi[0]) * X_HW[1] +(uint64_t)(two_over_pi[1]) * X_HW[0]); if(X_HW[2] == 0){ for(i=4; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-3]) * X_HW[1] +(uint64_t)(two_over_pi[i-2]) * X_HW[0]); }}else { for(i=4; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-4]) * X_HW[2] +(uint64_t)(two_over_pi[i-3]) * X_HW[1] +(uint64_t)(two_over_pi[i-2]) * X_HW[0]); } } }else { if (X_IND == 0){ r[0] = 0; r[1] = (uint64_t)(two_over_pi[0]) * X_HW[0]; r[2] = ((uint64_t)(two_over_pi[0]) * X_HW[1] +(uint64_t)(two_over_pi[1]) * X_HW[0]); if(X_HW[2] == 0){ for(i=3; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-2]) * X_HW[1] +(uint64_t)(two_over_pi[i-1]) * X_HW[0]); }}else { for(i=3; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-3]) * X_HW[2] +(uint64_t)(two_over_pi[i-2]) * X_HW[1] +(uint64_t)(two_over_pi[i-1]) * X_HW[0]); }} }else { if (X_IND == 1){ r[0] = (uint64_t)(two_over_pi[0]) * X_HW[0]; r[1] = ((uint64_t)(two_over_pi[0]) * X_HW[1] +(uint64_t)(two_over_pi[1]) * X_HW[0]); if(X_HW[2] == 0){ for(i=2; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-1]) * X_HW[1] +(uint64_t)(two_over_pi[ i ]) * X_HW[0]); }}else { for(i=2; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-2]) * X_HW[2] +(uint64_t)(two_over_pi[i-1]) * X_HW[1] +(uint64_t)(two_over_pi[ i ]) * X_HW[0]); }} }else { if (X_IND == 2){ r[0] = ((uint64_t)(two_over_pi[0]) * X_HW[1] +(uint64_t)(two_over_pi[1]) * X_HW[0]); if(X_HW[2] == 0){ for(i=1; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[ i ]) * X_HW[1] +(uint64_t)(two_over_pi[i+1]) * X_HW[0]); }}else { for(i=1; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi[i-1]) * X_HW[2] +(uint64_t)(two_over_pi[ i ]) * X_HW[1] +(uint64_t)(two_over_pi[i+1]) * X_HW[0]); }} }else { ind = (X_IND - 3); two_over_pi_pt = (int*)&(two_over_pi[ind]); if(X_HW[2] == 0){ for(i=0; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi_pt[i+1]) * X_HW[1] +(uint64_t)(two_over_pi_pt[i+2]) * X_HW[0]); }}else { for(i=0; i<(SCS_NB_WORDS+3); i++){ r[i] = ((uint64_t)(two_over_pi_pt[ i ]) * X_HW[2] +(uint64_t)(two_over_pi_pt[i+1]) * X_HW[1] +(uint64_t)(two_over_pi_pt[i+2]) * X_HW[0]); } } } } } } /* Carry propagate */ r[SCS_NB_WORDS+1] += r[SCS_NB_WORDS+2]>>30; for(i=(SCS_NB_WORDS+1); i>0; i--) {tmp=r[i]>>30; r[i-1] += tmp; r[i] -= (tmp<<30);} /* The integer part is in r[0] */ N = (unsigned int)(r[0]); #if 0 printf("r[0] = %d\n", N); #endif /* test if the reduced part is bigger than Pi/4 */ if (r[1] > (uint64_t)(SCS_RADIX)/2){ N += 1; sign = -1; for(i=1; i<(SCS_NB_WORDS+3); i++) { r[i]=((~(unsigned int)(r[i])) & 0x3fffffff);} } else sign = 1; /* Now we get the reduce argument and check for possible * cancellation By Kahan algorithm we will have at most 2 digits * of cancellations r[1] and r[2] in the worst case. */ if (r[1] == 0) if (r[2] == 0) i = 3; else i = 2; else i = 1; for(j=0; j<SCS_NB_WORDS; j++) { R_HW[j] = (unsigned int)(r[i+j]);} R_EXP = 1; R_IND = -i; R_SGN = sign*X_SGN; /* Last step : * Multiplication by pi/2 */ scs_mul(result, Pio2_ptr, result); return X_SGN*N; }
/************************************************************* ************************************************************* * 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; }
static void scs_atan(scs_ptr res_scs, scs_ptr x){ scs_t X_scs, denom1_scs, denom2_scs, poly_scs, X2; scs_t atanbhihi,atanbhilo, atanblo, atanbhi, atanb; scs_t bsc_ptr; db_number db; double test; int k, i=31; scs_get_d(&db.d, x); #if EVAL_PERF crlibm_second_step_taken++; #endif /* test if x as to be reduced */ if (db.d > MIN_REDUCTION_NEEDED) { /* Compute i so that x E [a[i],a[i+1]] */ if (db.d < arctan_table[i][A].d) i-= 16; else i+=16; if (db.d < arctan_table[i][A].d) i-= 8; else i+= 8; if (db.d < arctan_table[i][A].d) i-= 4; else i+= 4; if (db.d < arctan_table[i][A].d) i-= 2; else i+= 2; if (db.d < arctan_table[i][A].d) i-= 1; else if (i<61) i+= 1; if (db.d < arctan_table[i][A].d) i-= 1; /* evaluate X = (x - b(i)) / (1 + x*b(i)) */ scs_set_d(bsc_ptr, arctan_table[i][B].d); scs_mul(denom1_scs,bsc_ptr,x); scs_add(denom2_scs,denom1_scs,SCS_ONE); scs_sub(X_scs,x,bsc_ptr); scs_div(X_scs,X_scs,denom2_scs); scs_get_d(&test,X_scs); /* Polynomial evaluation of atan(X) , X = (x-b(i)) / (1+ x*b(i)) */ scs_square(X2, X_scs); scs_set(res_scs, constant_poly_ptr[0]); for(k=1; k < 10; k++) { /* we use Horner expression */ scs_mul(res_scs, res_scs, X2); scs_add(res_scs, constant_poly_ptr[k], res_scs); } scs_mul(poly_scs, res_scs, X_scs); /* reconstruction : */ /* 1st we load atan ( b[i] ) in a scs*/ scs_set_d( atanbhihi , arctan_table[i][ATAN_BHI].d); scs_set_d( atanbhilo , arctan_table[i][ATAN_BLO].d); scs_set_d( atanblo , atan_blolo[i].d); scs_add(atanbhi,atanbhihi,atanbhilo); scs_add(atanb,atanbhi,atanblo); scs_add(res_scs,atanb, poly_scs); return; } else { /* no reduction needed */ /* Polynomial evaluation of atan(x) */ scs_square(X2, x); scs_set(res_scs, constant_poly_ptr[0]); for(k=1; k < 10; k++) { /* we use Horner expression */ scs_mul(res_scs, res_scs, X2); scs_add(res_scs, constant_poly_ptr[k], res_scs); } scs_mul(res_scs, res_scs, x); return; } }