123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- /* ltstd.c */
- /* Function test routine.
- * Requires long double type check routine and double precision function
- * under test. Indicate function name and range in #define statements
- * below. Modifications for two argument functions and absolute
- * rather than relative accuracy report are indicated.
- */
- #include <stdio.h>
- /* int printf(), gets(), sscanf(); */
- #include <math.h>
- #ifdef ANSIPROT
- int drand ( void );
- int dprec ( void );
- int ldprec ( void );
- double exp ( double );
- double sqrt ( double );
- double fabs ( double );
- double floor ( double );
- long double sqrtl ( long double );
- long double fabsl ( long double );
- #else
- int drand();
- int dprec(), ldprec();
- double exp(), sqrt(), fabs(), floor();
- long double sqrtl(), fabsl();
- #endif
- #define RELERR 1
- #define ONEARG 0
- #define ONEINT 0
- #define TWOARG 0
- #define TWOINT 0
- #define THREEARG 1
- #define THREEINT 0
- #define FOURARG 0
- #define VECARG 0
- #define FOURANS 0
- #define TWOANS 0
- #define PROB 0
- #define EXPSCALE 0
- #define EXPSC2 0
- /* insert function to be tested here: */
- #define FUNC hyperg
- double FUNC();
- #define QFUNC hypergl
- long double QFUNC();
- /*extern int aiconf;*/
- extern double MAXLOG;
- extern double MINLOG;
- extern double MAXNUM;
- #define LTS 3.258096538
- /* insert low end and width of test interval */
- #define LOW 0.0
- #define WIDTH 30.0
- #define LOWA 0.0
- #define WIDTHA 30.0
- /* 1.073741824e9 */
- /* 2.147483648e9 */
- long double qone = 1.0L;
- static long double q1, q2, q3, qa, qb, qc, qz, qy1, qy2, qy3, qy4;
- static double y2, y3, y4, a, b, c, x, y, z, e;
- static long double qe, qmax, qrmsa, qave;
- volatile double v;
- static long double lp[3], lq[3];
- static double dp[3], dq[3];
- char strave[20];
- char strrms[20];
- char strmax[20];
- double underthresh = 2.22507385850720138309E-308; /* 2^-1022 */
- void main()
- {
- char s[80];
- int i, j, k;
- long m, n;
- merror = 0;
- ldprec(); /* set up coprocessor. */
- /*aiconf = -1;*/ /* configure Airy function */
- x = 1.0;
- z = x * x;
- qmax = 0.0L;
- sprintf(strmax, "%.4Le", qmax );
- qrmsa = 0.0L;
- qave = 0.0L;
- #if 1
- printf(" Start at random number #:" );
- gets( s );
- sscanf( s, "%ld", &n );
- printf("%ld\n", n );
- #else
- n = 0;
- #endif
- for( m=0; m<n; m++ )
- drand( &x );
- n = 0;
- m = 0;
- x = floor( x );
- loop:
- for( i=0; i<500; i++ )
- {
- n++;
- m++;
- #if ONEARG || TWOARG || THREEARG || FOURARG
- /*ldprec();*/ /* set up floating point coprocessor */
- /* make random number in desired range */
- drand( &x );
- x = WIDTH * ( x - 1.0 ) + LOW;
- #if EXPSCALE
- x = exp(x);
- drand( &a );
- a = 1.0e-13 * x * a;
- if( x > 0.0 )
- x -= a;
- else
- x += a;
- #endif
- #if ONEINT
- k = x;
- x = k;
- #endif
- v = x;
- q1 = v; /* double number to q type */
- #endif
- /* do again if second argument required */
- #if TWOARG || THREEARG || FOURARG
- drand( &a );
- a = WIDTHA * ( a - 1.0 ) + LOWA;
- /*a /= 50.0;*/
- #if EXPSC2
- a = exp(a);
- drand( &y2 );
- y2 = 1.0e-13 * y2 * a;
- if( a > 0.0 )
- a -= y2;
- else
- a += y2;
- #endif
- #if TWOINT || THREEINT
- k = a + 0.25;
- a = k;
- #endif
- v = a;
- qy4 = v;
- #endif
- #if THREEARG || FOURARG
- drand( &b );
- #if PROB
- /*
- b = b - 1.0;
- b = a * b;
- */
- #if 1
- /* This makes b <= a, for bdtr. */
- b = (a - LOWA) * ( b - 1.0 ) + LOWA;
- if( b > 1.0 && a > 1.0 )
- b -= 1.0;
- else
- {
- a += 1.0;
- k = a;
- a = k;
- v = a;
- qy4 = v;
- }
- #else
- b = WIDTHA * ( b - 1.0 ) + LOWA;
- #endif
- /* Half-integer a and b */
- /*
- a = 0.5*floor(2.0*a+1.0);
- b = 0.5*floor(2.0*b+1.0);
- */
- v = a;
- qy4 = v;
- /*x = (a / (a+b));*/
- #else
- b = WIDTHA * ( b - 1.0 ) + LOWA;
- #endif
- #if THREEINT
- j = b + 0.25;
- b = j;
- #endif
- v = b;
- qb = v;
- #endif
- #if FOURARG
- drand( &c );
- c = WIDTHA * ( c - 1.0 ) + LOWA;
- /* for hyp2f1 to ensure c-a-b > -1 */
- /*
- z = c-a-b;
- if( z < -1.0 )
- c -= 1.6 * z;
- */
- v = c;
- qc = v;
- #endif
- #if VECARG
- for( j=0; j<3; j++)
- {
- drand( &x );
- x = WIDTH * ( x - 1.0 ) + LOW;
- v = x;
- dp[j] = v;
- q1 = v; /* double number to q type */
- lp[j] = q1;
- drand( &x );
- x = WIDTH * ( x - 1.0 ) + LOW;
- v = x;
- dq[j] = v;
- q1 = v; /* double number to q type */
- lq[j] = q1;
- }
- #endif /* VECARG */
- /*printf("%.16E %.16E\n", a, x);*/
- /* compute function under test */
- /* Set to double precision */
- /*dprec();*/
- #if ONEARG
- #if FOURANS
- /*FUNC( x, &z, &y2, &y3, &y4 );*/
- FUNC( x, &y4, &y2, &y3, &z );
- #else
- #if TWOANS
- FUNC( x, &z, &y2 );
- /*FUNC( x, &y2, &z );*/
- #else
- #if ONEINT
- z = FUNC( k );
- #else
- z = FUNC( x );
- #endif
- #endif
- #endif
- #endif
- #if TWOARG
- #if TWOINT
- z = FUNC( k, x );
- /*z = FUNC( x, k );*/
- /*z = FUNC( a, x );*/
- #else
- #if FOURANS
- FUNC( a, x, &z, &y2, &y3, &y4 );
- #else
- z = FUNC( a, x );
- #endif
- #endif
- #endif
- #if THREEARG
- #if THREEINT
- z = FUNC( j, k, x );
- #else
- z = FUNC( a, b, x );
- #endif
- #endif
- #if FOURARG
- z = FUNC( a, b, c, x );
- #endif
- #if VECARG
- z = FUNC( dp, dq );
- #endif
- q2 = z;
- /* handle detected overflow */
- if( (z == MAXNUM) || (z == -MAXNUM) )
- {
- printf("detected overflow ");
- #if FOURARG
- printf("%.4E %.4E %.4E %.4E %.4E %6ld \n",
- a, b, c, x, y, n);
- #else
- printf("%.16E %.4E %.4E %6ld \n", x, a, z, n);
- #endif
- e = 0.0;
- m -= 1;
- goto endlup;
- }
- /* Skip high precision if underflow. */
- if( merror == UNDERFLOW )
- goto underf;
- /* compute high precision function */
- /*ldprec();*/
- #if ONEARG
- #if FOURANS
- /*qy4 = QFUNC( q1, qz, qy2, qy3 );*/
- qz = QFUNC( q1, qy4, qy2, qy3 );
- #else
- #if TWOANS
- qy2 = QFUNC( q1, qz );
- /*qz = QFUNC( q1, qy2 );*/
- #else
- /* qy4 = 0.0L;*/
- /* qy4 = 1.0L;*/
- /*qz = QFUNC( qy4, q1 );*/
- /*qz = QFUNC( 1, q1 );*/
- qz = QFUNC( q1 ); /* normal */
- #endif
- #endif
- #endif
- #if TWOARG
- #if TWOINT
- qz = QFUNC( k, q1 );
- /*qz = QFUNC( q1, qy4 );*/
- /*qz = QFUNC( qy4, q1 );*/
- #else
- #if FOURANS
- qc = QFUNC( qy4, q1, qz, qy2, qy3 );
- #else
- /*qy4 = 0.0L;;*/
- /*qy4 = 1.0L );*/
- qz = QFUNC( qy4, q1 );
- #endif
- #endif
- #endif
- #if THREEARG
- #if THREEINT
- qz = QFUNC( j, k, q1 );
- #else
- qz = QFUNC( qy4, qb, q1 );
- #endif
- #endif
- #if FOURARG
- qz = QFUNC( qy4, qb, qc, q1 );
- #endif
- #if VECARG
- qz = QFUNC( lp, lq );
- #endif
- y = qz; /* correct answer, in double precision */
- /* get absolute error, in extended precision */
- qe = q2 - qz;
- e = qe; /* the error in double precision */
- /* handle function result equal to zero
- or underflowed. */
- if( qz == 0.0L || merror == UNDERFLOW || fabs(z) < underthresh )
- {
- underf:
- merror = 0;
- /* Don't bother to print anything. */
- #if 0
- printf("ans 0 ");
- #if ONEARG
- printf("%.8E %.8E %.4E %6ld \n", x, y, e, n);
- #endif
- #if TWOARG
- #if TWOINT
- printf("%d %.8E %.8E %.4E %6ld \n", k, x, y, e, n);
- #else
- printf("%.6E %.6E %.6E %.4E %6ld \n", a, x, y, e, n);
- #endif
- #endif
- #if THREEARG
- printf("%.6E %.6E %.6E %.6E %.4E %6ld \n", a, b, x, y, e, n);
- #endif
- #if FOURARG
- printf("%.4E %.4E %.4E %.4E %.4E %.4E %6ld \n",
- a, b, c, x, y, e, n);
- #endif
- #endif /* 0 */
- qe = 0.0L;
- e = 0.0;
- m -= 1;
- goto endlup;
- }
- else
- /* relative error */
- /* comment out the following two lines if absolute accuracy report */
- #if RELERR
- qe = qe / qz;
- #else
- {
- q2 = qz;
- q2 = fabsl(q2);
- if( q2 > 1.0L )
- qe = qe / qz;
- }
- #endif
- qave = qave + qe;
- /* absolute value of error */
- qe = fabs(qe);
- /* peak detect the error */
- if( qe > qmax )
- {
- qmax = qe;
- sprintf(strmax, "%.4Le", qmax );
- #if ONEARG
- printf("%.8E %.8E %s %6ld \n", x, y, strmax, n);
- #endif
- #if TWOARG
- #if TWOINT
- printf("%d %.8E %.8E %s %6ld \n", k, x, y, strmax, n);
- #else
- printf("%.6E %.6E %.6E %s %6ld \n", a, x, y, strmax, n);
- #endif
- #endif
- #if THREEARG
- printf("%.6E %.6E %.6E %.6E %s %6ld \n", a, b, x, y, strmax, n);
- #endif
- #if FOURARG
- printf("%.4E %.4E %.4E %.4E %.4E %s %6ld \n",
- a, b, c, x, y, strmax, n);
- #endif
- #if VECARG
- printf("%.8E %s %6ld \n", y, strmax, n);
- #endif
- }
- /* accumulate rms error */
- /* rmsa += e * e; accumulate the square of the error */
- q2 = qe * qe;
- qrmsa = qrmsa + q2;
- endlup: ;
- /*ldprec();*/
- }
- /* report every 500 trials */
- /* rms = sqrt( rmsa/m ); */
- q1 = m;
- q2 = qrmsa / q1;
- q2 = sqrtl(q2);
- sprintf(strrms, "%.4Le", q2 );
- q2 = qave / q1;
- sprintf(strave, "%.4Le", q2 );
- /*
- printf("%6ld max = %s rms = %s ave = %s \n", m, strmax, strrms, strave );
- */
- printf("%6ld max = %s rms = %s ave = %s \r", m, strmax, strrms, strave );
- fflush(stdout);
- goto loop;
- }
|