Last active
November 23, 2016 12:37
-
-
Save artemgurzhii/b9660f212ae1a56deecbf9c8f18f717a to your computer and use it in GitHub Desktop.
Recreation of native CLang log() and pow() functions which works with decimals.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <math.h> | |
#define MYLOG_N 12 | |
#define MTPOW_N 30 | |
#define EXP_VAL 2.718281828459045090795598298427648842334747314453125 | |
double cfrac_log(double x, unsigned int n) { | |
if (x < 0) { | |
return NAN; | |
} | |
if (x == 0) { | |
return -INFINITY; | |
} | |
double z = (x - 1.0) / (x + 1.0); | |
double result = 0.0; | |
unsigned int i; | |
for (i = n; i > 0; i--) { | |
result = (i * i * z * z) / ((i * 2.0 + 1.0) - result); | |
} | |
return 2.0 * z / (1.0 - result); | |
} | |
double logarithm(double x) { | |
if (x < 0.0 || isnan(x)) return NAN; | |
if (x == 0.0) return -INFINITY; | |
if (isinf(x)) return INFINITY; | |
int intResult = 0; | |
if (x >= 1.0) { | |
while (x >= EXP_VAL) { | |
x /= EXP_VAL; | |
intResult++; | |
} | |
return cfrac_log(x, MYLOG_N) + intResult; | |
} else { | |
while (x < 1.0) { | |
x *= EXP_VAL; | |
intResult++; | |
} | |
return cfrac_log(x, MYLOG_N) - intResult; | |
} | |
} | |
double power(double x, double y) { | |
if (isnan(x) || isnan(y)) return NAN; | |
if (x < 0) return -NAN; | |
if (isinf(x) || isinf(y)) return INFINITY; | |
int isPositiveY = y > 0; | |
if (!isPositiveY) { | |
y = -y; | |
} | |
int integerY = (int) y; | |
double result1 = 1.0; | |
double x1 = x; | |
while (integerY) { | |
if (integerY & 1) { | |
result1 *= x1; | |
} | |
integerY >>= 1; | |
x1 *= x1; | |
} | |
double result2 = 1.0; | |
double numerator = (y - (int)y) * (x); | |
double currentValue = 1.0; | |
for (unsigned int i = 1; i <= MTPOW_N; i++) { | |
result2 += (currentValue *= numerator / i); | |
} | |
return isPositiveY ? result1 * result2 : 1 / (result1 * result2); | |
} | |
int main() { | |
double numb = 79000000; | |
printf("Power: Native - %.7e, written - %.7e\n", pow(numb, numb), power(numb, numb)); | |
printf("Log: Native - %.7e, written - %.7e\n", log(numb), logarithm(numb)); | |
return 0; | |
} | |
// RESULTS | |
// Test are only shown for first 7 digits returned by function call | |
// 'power' and 'logarithm' functions returns same values as native for all numbers | |
// NOTE: values returned under are same for first 7 digits after dot. Real diffrence is may be bigger |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment