Using the three user-implemented functions iPow(x, n) , Ln(x) and Exp(x) , I can calculate fPow(x, a) , x and a doubles . None of the functions below use library functions, but just an iteration.
Some explanation about the implemented functions:
(1) iPow(x, n) : x is double , n - int . This is a simple iteration, since n is an integer.
(2) Ln(x) : This function uses iteration of the Taylor series. The series used in the iteration is Σ (from int i = 0 to n) {(1 / (2 * i + 1)) * ((x - 1) / (x + 1)) ^ (2 * n + 1)} . The symbol ^ denotes the power function Pow(x, n) , implemented in the first function, which uses a simple iteration.
(3) Exp(x) : This function again uses the iteration of the Taylor series. The series used in the iteration is Σ (from int i = 0 to n) {x^i / i!} . Here ^ denotes a force function, but it is not calculated by calling function 1 Pow(x, n) ; instead, it is implemented within the framework of the third function, simultaneously with the factorial, using d *= x / i . I felt that I had to use this trick because iteration takes several steps in this function compared to other functions, and factorial (i!) Overflows most of the time. To make sure that the iteration is not crowded, the power function in this part is repeated simultaneously with the factorial. So I overcame the overflow.
(4) fPow(x, a) : x and a both double . This function does nothing, but simply calls the other three functions implemented above. The basic idea of this function depends on some calculus: fPow(x, a) = Exp(a * Ln(x)) . And now I have all the functions of iPow , Ln and Exp with iteration already.
nb I used constant MAX_DELTA_DOUBLE to decide at what stage to stop the iteration. I set it to 1.0E-15 , which seems reasonable for the pair. So, the iteration stops if (delta < MAX_DELTA_DOUBLE) If you need higher precision, you can use long double and decrease the constant value for MAX_DELTA_DOUBLE , 1.0E-18 for example (1.0E-18 will be minimal).
Here is the code that works for me.
#define MAX_DELTA_DOUBLE 1.0E-15 #define EULERS_NUMBER 2.718281828459045 double MathAbs_Double (double x) { return ((x >= 0) ? x : -x); } int MathAbs_Int (int x) { return ((x >= 0) ? x : -x); } double MathPow_Double_Int(double x, int n) { double ret; if ((x == 1.0) || (n == 1)) { ret = x; } else if (n < 0) { ret = 1.0 / MathPow_Double_Int(x, -n); } else { ret = 1.0; while (n--) { ret *= x; } } return (ret); } double MathLn_Double(double x) { double ret = 0.0, d; if (x > 0) { int n = 0; do { int a = 2 * n + 1; d = (1.0 / a) * MathPow_Double_Int((x - 1) / (x + 1), a); ret += d; n++; } while (MathAbs_Double(d) > MAX_DELTA_DOUBLE); } else { printf("\nerror: x < 0 in ln(x)\n"); exit(-1); } return (ret * 2); } double MathExp_Double(double x) { double ret; if (x == 1.0) { ret = EULERS_NUMBER; } else if (x < 0) { ret = 1.0 / MathExp_Double(-x); } else { int n = 2; double d; ret = 1.0 + x; do { d = x; for (int i = 2; i <= n; i++) { d *= x / i; } ret += d; n++; } while (d > MAX_DELTA_DOUBLE); } return (ret); } double MathPow_Double_Double(double x, double a) { double ret; if ((x == 1.0) || (a == 1.0)) { ret = x; } else if (a < 0) { ret = 1.0 / MathPow_Double_Double(x, -a); } else { ret = MathExp_Double(a * MathLn_Double(x)); } return (ret); }