Changeset 5181ccc in sasmodels for sasmodels/models/lib


Ignore:
Timestamp:
May 19, 2017 8:13:16 AM (7 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, costrafo411, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
487e695
Parents:
f102a96
Message:

improve accuracy of bessel function J1

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/models/lib/sas_J1.c

    reb2946f r5181ccc  
    109109{ 
    110110 
    111     double w, z, p, q, xn, abs_x, sign_x; 
     111    double w, z, p, q, abs_x, sign_x; 
    112112 
    113113    const double Z1 = 1.46819706421238932572E1; 
    114114    const double Z2 = 4.92184563216946036703E1; 
    115     const double THPIO4 =  2.35619449019234492885; 
    116     const double SQ2OPI = 0.79788456080286535588; 
    117115 
    118116    // 2017-05-18 PAK - mathematica and mpmath use J1(-x) = -J1(x) 
     
    136134    p = polevl( z, PPJ1, 6)/polevl( z, PQJ1, 6 ); 
    137135    q = polevl( z, QPJ1, 7)/p1evl( z, QQJ1, 7 ); 
    138     xn = abs_x - THPIO4; 
    139  
    140     double sn, cn; 
    141     SINCOS(xn, sn, cn); 
    142     p = p * cn - w * q * sn; 
    143  
    144     return( sign_x * p * SQ2OPI / sqrt(abs_x) ); 
     136 
     137    // 2017-05-19 PAK improve accuracy using trig identies 
     138    // original: 
     139    //    const double THPIO4 =  2.35619449019234492885; 
     140    //    const double SQ2OPI = 0.79788456080286535588; 
     141    //    double sin_xn, cos_xn; 
     142    //    SINCOS(abs_x - THPIO4, sin_xn, cos_xn); 
     143    //    p = p * cos_xn - w * q * sin_xn; 
     144    //    return( sign_x * p * SQ2OPI / sqrt(abs_x) ); 
     145    // expanding p*cos(a - 3 pi/4) - wq sin(a - 3 pi/4) 
     146    //    [ p(sin(a) - cos(a)) + wq(sin(a) + cos(a)) / sqrt(2) 
     147    // note that sqrt(1/2) * sqrt(2/pi) = sqrt(1/pi) 
     148    const double SQRT1_PI = 0.56418958354775628; 
     149    double sin_x, cos_x; 
     150    SINCOS(abs_x, sin_x, cos_x); 
     151    p = p*(sin_x - cos_x) + w*q*(sin_x + cos_x); 
     152    return( sign_x * p * SQRT1_PI / sqrt(abs_x) ); 
    145153} 
    146154 
     
    188196 
    189197    const float Z1 = 1.46819706421238932572E1; 
    190     const float THPIO4F =  2.35619449019234492885;    /* 3*pi/4 */ 
    191198 
    192199 
     
    207214    p = w * polevl( q, MO1J1, 7); 
    208215    w = q*q; 
    209     xn = q * polevl( w, PH1J1, 7) - THPIO4F; 
    210     p = p * cos(xn + x); 
     216    // 2017-05-19 PAK improve accuracy using trig identies 
     217    // original: 
     218    //    const float THPIO4F =  2.35619449019234492885;    /* 3*pi/4 */ 
     219    //    xn = q * polevl( w, PH1J1, 7) - THPIO4F; 
     220    //    p = p * cos(xn + x); 
     221    //    return( xx < 0. ? -p : p ); 
     222    // expanding cos(a + b - 3 pi/4) is 
     223    //    [sin(a)sin(b) + sin(a)cos(b) + cos(a)sin(b)-cos(a)cos(b)] / sqrt(2) 
     224    xn = q * polevl( w, PH1J1, 7); 
     225    float cos_xn, sin_xn; 
     226    float cos_x, sin_x; 
     227    SINCOS(xn, sin_xn, cos_xn);  // about xn and 1 
     228    SINCOS(x, sin_x, cos_x); 
     229    p *= M_SQRT1_2*(sin_xn*(sin_x+cos_x) + cos_xn*(sin_x-cos_x)); 
    211230 
    212231    return( xx < 0. ? -p : p ); 
Note: See TracChangeset for help on using the changeset viewer.