//****************************************************************** // Schroder's Methods A and B for the calculation of square roots. // Reference: "On Infinitely Many Algorithms For Solving Equations" // by Ernst Schroder, Translated by G. W. Stewart. // ---------------------------------------------------------------- // For each value of Omega, we calculate A and B then average. // ---------------------------------------------------------------- // For this family of equations, we consider the equations when the // parameter Lambda is zero. Some methods where Lambda is not zero // will generate identical equations. Some of these are noted in // the comments. For square root, method A and Method B for the // same Lamda and Omega are closely related to each other. For // each equation, if we are finding the square root of c, then our // estimate k can be used to form the other equation by the // transformation: y = c/k. This is also obvious since: // c/sqrt( c ) = c^( 1/2 ) // gives us the square root of c also, with an estimate k, then c/k // gives us a new estimate. Taking the average is the equivalent // of a Newton step at the end. // ---------------------------------------------------------------- // Copyright (C) 1996 by Dann Corbit //****************************************************************** #include "sqrts.h" //****************************************************************** // Schroder's Method( A, Lamda=0, Omega = 1 ) for x*x - c = 0 // SqrtNewt( ) produces 2 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtNewt( NUMBER x, NUMBER c ) { return ( x * x + c ) / x * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 1 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega = 1 ) for x*x - c = 0 // SqrtAB01( ) produces 4 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. Ans0 is also "Newton's Method" for square root. //****************************************************************** NUMBER SqrtAB01( NUMBER x, NUMBER c ) { NUMBER ans0 = ( x * x + c ) / x * 0.5; NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 2 ) for x*x - c = 0 // Schroder's Method( B, Lamda=-1/2, Omega = 1 ) for x*x - c = 0 and // Schroder's Method( A, Lamda=1/2, Omega = 1 ) for x*x - c = 0 also // result in exactly the same equation. // Interesting, that lower order methods ( Omega=1 ) arrive at the // same equations as a higher order method ( Omega=2 ). This shows // that the convergence rate is a minimum limit, and that for a // given equation, at least one higher order of convergence may be // achieved. It may or may not be computationally more efficient. // SqrtAB02( ) produces 6 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB02( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER ans0 = x * ( x2 + 3. * c ) / ( 3. * x2 + c ); NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 3 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega = 3 ) for x*x - c = 0 // and Schroder's Method( B, Lamda=1, Omega = 3 ) for x*x - c= 0 // SqrtAB03( ) produces 8 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB03( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER ans0 = x - ( x2 - c ) / x * ( 3.0 * x2 + c ) / ( x2 + c ) * 0.25; NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 4 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega = 4 ) for x*x - c = 0 // SqrtAB04( ) produces 10 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB04( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER ans0 = x - 4.0 * ( x2 - c ) * x * ( x2 + c ) / ( 5.0 * x2 * x2 + 10.0 * x2 * c + c * c ); NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 5 ) for x*x - c = 0 // and Schroder's Method( B, Lamda=-1, Omega = 5 ) for x*x-c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega = 5 ) for x*x - c = 0 // and Schroder's Method( A, Lamda=1, Omega = 5 ) for x*x - c = 0 // SqrtAB05( ) produces 12 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB05( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER ans0 = ( x2 + c ) * ( x2 * x2 + 14.0 * x2 * c + c * c ) / x / ( 3.0 * x2 + c ) / ( x2 + 3.0 * c ) * 0.5; NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 6 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega = 6 ) for x*x - c = 0 // SqrtAB06( ) produces 14 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB06( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER c2 = c * c; NUMBER ans0 = x - 2.0 * ( x2 - c ) * x * ( 3.0 * x4 + 10.0 * x2 * c + 3.0 * c2 ) / ( 7.0 * x4 * x2 + 35.0 * x4 * c + 21.0 * x2 * c2 + c2 * c ); NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 7 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega = 7 ) for x*x - c = 0 // SqrtAB07( ) produces 16 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB07( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x8 = x4 * x4; NUMBER c2 = c * c; NUMBER c4 = c2 * c2; NUMBER ans0 = ( x4 * x4 + 28.0 * x4 * x2 * c + 70.0 * c2 * x4 + 28.0 * x2 * c2 * c + c2 * c2 ) / x / ( x2 + c ) / ( x4 + 6.0 * x2 * c + c2 ) * 0.125; NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 8 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega = 8 ) for x*x - c = 0 // SqrtAB08( ) produces 18 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB08( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER c2 = c * c; NUMBER ans0 = x + 8.0 * ( c - x2 ) * x * ( c + x2 ) * ( x4 + 6.0 * x2 * c + c2 ) / ( c + 3.0 * x2 ) / ( 3.0 * x4 * x2 + 27.0 * x4 * c + 33.0 * x2 * c2 + c2 * c ); NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega = 9 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega = 9 ) for x*x - c = 0 // SqrtAB09( ) produces 20 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB09( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x2c = x2 * c; NUMBER c2 = c * c; NUMBER x8 = x4 * x4; NUMBER c4 = c2 * c2; NUMBER ans0 = 2.0 * x * c * ( x4 + 10.0 * x2c + 5.0 * c2 ) * ( 5.0 * x4 + 10.0 * x2c + c2 ) / ( x2 + c ) / ( x8 + 44.0 * x4 * x2 * c + 166.0 * c2 * x4 + 44.0 * x2 * c2 * c + c4 ); NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega =10 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega =10 ) for x*x - c = 0 // SqrtAB010( ) produces 22 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB10( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x8 = x4 * x4; NUMBER x6 = x4 * x2; NUMBER c2 = c * c; NUMBER c3 = c2 * c; NUMBER c4 = c2 * c2; NUMBER ans0 = x - 2.0 * ( x2 - c ) * x * ( 5.0 * ( x8 + c4 )+ 60.0 * ( x6 * c + x2 * c3 )+ 126.0 * c2 * x4 ) / (x8 * ( 11.0 * x2 + 165.0 * c ) + 462.0 * x6 * c2 + 330.0 * c3 * x4 + c4 * ( 55.0 * x2 + c )); NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega =11 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega =11 ) for x*x - c = 0 // SqrtAB011( ) produces 24 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB11( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x2c = x2 * c; NUMBER c2 = c * c; NUMBER x8 = x4 * x4; NUMBER c4 = c2 * c2; NUMBER ans0 = ( x4 + 6.0 * x2c + c2 ) * ( x8 + 60.0 * x4 * x2 * c + 134.0 * c2 * x4 + 60.0 * x2 * c2 * c + c4 ) / x / ( x2 + c ) / ( x2 + 3.0 * c ) / ( 3.0 * x2 + c ) / ( x4 + 14.0 * x2c + c2 ) * 0.25; NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega =12 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega =12 ) for x*x - c = 0 // SqrtAB012( ) produces 26 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB12( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x8 = x4 * x4; NUMBER x10 = x8 * x2; NUMBER x6 = x4 * x2; NUMBER c2 = c * c; NUMBER c3 = c2 * c; NUMBER c4 = c2 * c2; NUMBER c5 = c4 * c; NUMBER ans0 = x - 4.0 * ( x2 - c ) * x * ( 3.0 * x10 + 55.0 * x8 * c + 198.0 * x6 * c2 + 198.0 * c3 * x4 + 55.0 * x2 * c4 + 3.0 * c5 ) / ( 13.0 * x8 * x4 + 286.0 * x10 * c + 1287.0 * x8 * c2 + 1716.0 * c3 * x6 + 715.0 * x4 * c4 + 78.0 * x2 * c5 + c4 * c2 ); NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega =13 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega =13 ) for x*x - c = 0 // SqrtAB013( ) produces 28 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB13( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x8 = x4 * x4; NUMBER c2 = c * c; NUMBER c3 = c2 * c; NUMBER x6 = x4 * x2; NUMBER c4 = c2 * c2; NUMBER x4c = x4 * c; NUMBER x2c2 = x2 * c2; NUMBER ans0 = ( x2 + c ) * ( x8 * x4 + 90.0 * x8 * x2 * c + 911.0 * x8 * c2 + 2092.0 * c3 * x6 + 911.0 * x4 * c4 + 90.0 * x2 * c4 * c + c4 * c2 ) / x / ( x6 + 21.0 * x4c + 35.0 * x2c2 + 7.0 * c3 ) / ( 7.0 * x6 + 35.0 * x4c + 21.0 * x2c2 + c3 ) * 0.5; NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega =14 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega =14 ) for x*x - c = 0 // SqrtAB014( ) produces 30 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB14( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x6 = x4 * x2; NUMBER x8 = x4 * x4; NUMBER x14 = x8 * x6; NUMBER c2 = c * c; NUMBER c3 = c2 * c; NUMBER c4 = c2 * c2; NUMBER c7 = c4 * c3; NUMBER x2c6 = x2 * c4 * c2; NUMBER x4c5 = x4 * c4 * c; NUMBER x6c4 = x6 * c4; NUMBER x8c3 = x8 * c3; NUMBER x10c2 = x8 * x2 * c2; NUMBER x12c = x8 * x4 * c; NUMBER ans0 = x * ( 105. * x12c + 1365. * x10c2 + 455. * x2c6 + 5005. * x8c3 + 3003. * x4c5 + 6435. * x6c4 + 15. * c7 + x14 ) / ( 455. * x12c + 3003. * x10c2 + 105. * x2c6 + 6435. * x8c3 + 1365. * x4c5 + 5005. * x6c4 + c7 + 15. * x14 ); NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega =15 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega =15 ) for x*x - c = 0 // SqrtAB015( ) produces 32 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB15( NUMBER x, NUMBER c ) { NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x6 = x4 * x2; NUMBER x8 = x4 * x4; NUMBER x10 = x8 * x2; NUMBER x12 = x8 * x4; NUMBER x14 = x8 * x6; NUMBER x16 = x8 * x8; NUMBER c2 = c * c; NUMBER c3 = c2 * c; NUMBER c4 = c2 * c2; NUMBER c5 = c4 * c; NUMBER c6 = c4 * c2; NUMBER c7 = c4 * c3; NUMBER c8 = c4 * c4; NUMBER ans1 = 16. * x * c * ( 35. * ( x12 * c + x2 * c6 ) + 273. * ( x10 * c2 + x4 * c5 ) + 715. * ( x8 * c3 + x6 * c4 ) + c7 + x14 ) / ( 120. * ( x14 * c + x2 * c7 ) + 1820. * ( x12 * c2 + x4 * c6 ) + 8008. * ( x10 * c3 + x6 * c5 ) + 12870. * x8 * c4 + x16 + c8 ); NUMBER ans0 = c / ans1; return ( ans0 + ans1 ) * 0.5; } //****************************************************************** // Ans0 is Schroder's Method( A, Lamda=0, Omega =19 ) for x*x - c = 0 // Ans1 is Schroder's Method( B, Lamda=0, Omega =19 ) for x*x - c = 0 // SqrtAB019( ) produces 40 times as many correct digits after each // iteration, if the initial guess x has at least one significant // digit correct. //****************************************************************** NUMBER SqrtAB19( NUMBER x, NUMBER c ) { NUMBER c2 = c * c; NUMBER c3 = c2 * c; NUMBER c4 = c3 * c; NUMBER c5 = c4 * c; NUMBER c6 = c5 * c; NUMBER c7 = c6 * c; NUMBER c8 = c7 * c; NUMBER c9 = c8 * c; NUMBER c10 = c9 * c; NUMBER x2 = x * x; NUMBER x4 = x2 * x2; NUMBER x6 = x4 * x2; NUMBER x8 = x6 * x2; NUMBER x10 = x8 * x2; NUMBER x12 = x10 * x2; NUMBER x14 = x12 * x2; NUMBER x16 = x14 * x2; NUMBER x18 = x16 * x2; NUMBER x20 = x18 * x2; NUMBER x8c4 = x8 * c4; NUMBER x4c2 = x4 * c2; NUMBER x6c3 = x6 * c3; NUMBER x2c = x2 * c; NUMBER poly1 = 184756. * x10 * c5 + 125970. * x8c4 * ( c2 + x4 ) + x20 + 4845. * x4c2 * ( c6 + x12 ) + 38760. * x6c3 * ( c4 + x8 ) + 190. * x2c * ( c8 + x16 ) + c10; NUMBER poly4 = 4. * x * ( 41990. * x8c4 * ( c + x2 ) + 19380. * x6c3 * ( c3 + x6 ) + 5. * ( c9 + x18 ) + 285. * x2c * ( c7 + x14 ) + 3876. * x4c2 * ( c5 + x10 ) ); NUMBER ans0 = poly1 / poly4; NUMBER ans1 = c / ans0; return ( ans0 + ans1 ) * 0.5; } #ifdef TEST #include #include #include #include #include void block( NUMBER x, NUMBER k, int noisy ); void timeit( NUMBER x, NUMBER k, int which ); int main( int argc, char **argv ) { NUMBER k; NUMBER x; NUMBER fudge_factor = 2.0; NUMBER answer; long i; int noisy = 1; int which; char pszString[256] = "2"; clock_t cstart; double delta; cout.precision( 18 ); if ( argc < 2 ) { cout << "Enter a number to find square root of:"; cin >> pszString; cout << pszString; } else strncpy( pszString, argv[1], sizeof( pszString ) ); k = atof( pszString ); answer = sqrtl( k ); cout << "\nLib Answer: " << answer; for ( i = 0; i < 5; i++ ) { fudge_factor = sqrtl( fudge_factor ); x = answer * fudge_factor; // Guess too high if ( noisy ) cout << "\n\nBad Guess High: " << x; block( x, k, noisy ); x = answer / fudge_factor; // Guess too low if ( noisy ) cout << "\n\nBad Guess Low: " << x; block( x, k, noisy ); } noisy = 0; for ( which = 0; which <= 16; which++ ) { cstart = clock( ); fudge_factor = sqrtl( fudge_factor ); for ( i = 0; i < 500000; i++ ) { x = answer * fudge_factor; // Guess too high timeit( x, k, which ); x = answer / fudge_factor; // Guess too low timeit( x, k, which ); x = answer * fudge_factor; // Guess too high timeit( x, k, which ); x = answer / fudge_factor; // Guess too low timeit( x, k, which ); x = answer * fudge_factor; // Guess too high timeit( x, k, which ); x = answer / fudge_factor; // Guess too low timeit( x, k, which ); } delta = ( clock( ) - cstart ) / ( double ) CLOCKS_PER_SEC; if ( which == 0 ) cout << "\nNewton-" << which << " " << delta << " seconds.\n" << endl; else if ( which < 16 ) cout << "\nOmega-" << which << " " << delta << " seconds.\n" << endl; else cout << "\nEmpty-" << which << " " << delta << " seconds.\n" << endl; } return 0; } void block( NUMBER x, NUMBER k, int noisy ) { NUMBER answer; answer = SqrtAB01( x, k ); if ( noisy ) cout << "\nAB01 - estimate: " << answer; answer = SqrtAB02( x, k ); if ( noisy ) cout << "\nAB02 - estimate: " << answer; answer = SqrtAB03( x, k ); if ( noisy ) cout << "\nAB03 - estimate: " << answer; answer = SqrtAB04( x, k ); if ( noisy ) cout << "\nAB04 - estimate: " << answer; answer = SqrtAB05( x, k ); if ( noisy ) cout << "\nAB05 - estimate: " << answer; answer = SqrtAB06( x, k ); if ( noisy ) cout << "\nAB06 - estimate: " << answer; answer = SqrtAB07( x, k ); if ( noisy ) cout << "\nAB07 - estimate: " << answer; answer = SqrtAB08( x, k ); if ( noisy ) cout << "\nAB08 - estimate: " << answer; answer = SqrtAB09( x, k ); if ( noisy ) cout << "\nAB09 - estimate: " << answer; answer = SqrtAB10( x, k ); if ( noisy ) cout << "\nAB10 - estimate: " << answer; answer = SqrtAB11( x, k ); if ( noisy ) cout << "\nAB11 - estimate: " << answer; answer = SqrtAB12( x, k ); if ( noisy ) cout << "\nAB12 - estimate: " << answer; answer = SqrtAB13( x, k ); if ( noisy ) cout << "\nAB13 - estimate: " << answer; answer = SqrtAB14( x, k ); if ( noisy ) cout << "\nAB14 - estimate: " << answer; answer = SqrtAB15( x, k ); if ( noisy ) cout << "\nAB15 - estimate: " << answer; } void timeit( NUMBER x, NUMBER k, int which ) { NUMBER answer; switch ( which ) { case 0: answer = SqrtNewt( x, k ); break; case 1: answer = SqrtAB01( x, k ); break; case 2: answer = SqrtAB02( x, k ); break; case 3: answer = SqrtAB03( x, k ); break; case 4: answer = SqrtAB04( x, k ); break; case 5: answer = SqrtAB05( x, k ); break; case 6: answer = SqrtAB06( x, k ); break; case 7: answer = SqrtAB07( x, k ); break; case 8: answer = SqrtAB08( x, k ); break; case 9: answer = SqrtAB09( x, k ); break; case 10: answer = SqrtAB10( x, k ); break; case 11: answer = SqrtAB11( x, k ); break; case 12: answer = SqrtAB12( x, k ); break; case 13: answer = SqrtAB13( x, k ); break; case 14: answer = SqrtAB14( x, k ); break; case 15: answer = SqrtAB15( x, k ); break; default: // Empty timing loop pass break; } return; } #endif