Skip to content

Instantly share code, notes, and snippets.

@chongkong
Last active September 26, 2020 09:32
Show Gist options
  • Save chongkong/efbe0c1bbabbc08d461e4d067fc39030 to your computer and use it in GitHub Desktop.
Save chongkong/efbe0c1bbabbc08d461e4d067fc39030 to your computer and use it in GitHub Desktop.
Code feedback for ibaesuyeon
#include <stdio.h>
#include <math.h>
// Consistent code styling is important.
// This is my preference, but I uses "2 spaces" for indentation
// (as opposed to using "tab") because github renders tab with 8 spaces.
// You can configure your code editor to use spaces instead of tab,
// even when you're pressing a tab.
// Recursive style factorial function. Returns x!.
long long factorial(int x) {
// "LL" in 1LL is the literal suffix to use the long long value.
// See https://boycoding.tistory.com/155.
return (x <= 1) ? 1LL : (long long)(x) * factorial(x - 1);
}
// Recursive style power function. Returns x^exp.
double power(double x, int exp) {
return (exp <= 0) ? 1.0 : x * power(x, exp - 1);
}
// sin(x) taylor approximation with naive implementation.
double sin_taylor_naive(double rad, int max_order) {
// fmod is a modular operation for floating point value (thus the name fmod).
// Clip values outside -pi <= rad <= pi.
rad = fmod(rad, M_PI);
double result = 0.0;
for (int k = 1; k <= max_order; k += 2) {
// "Sign" is a computer science term whether the value is positive or negative.
double sign = (k % 4 == 3) ? -1 : 1;
// Large value divided by large value is numerically unstable.
result += sign * power(rad, k) / factorial(k);
// Un-comment below to see how coefficients goes Inf or NaN when k is big.
// printf("DEBUG: k=%d sign=%1.0lf power=%lf coef=%lf\n",
// k, sign, power(rad, k), 1.0 / factorial(k));
}
return result;
}
// sin(x) taylor approximation with FMA (Fused multiplication-addition)
// implementation.
double sin_taylor_fma(double rad, int max_order) {
rad = fmod(rad, M_PI); // Clip values outside -pi <= rad <= pi.
double result = 1.0;
// Taylor expansion for sin(x) has only odd-order terms.
if (max_order % 2 == 0) max_order -= 1;
for (int k = max_order; k > 1; k -= 2) {
result = 1.0 - rad * rad / ((k - 1) * k) * result;
}
result *= rad;
return result;
}
int main() {
double degree;
int max_taylor_order;
// We use "Enter" instead of "Inject" on interactive command line program.
printf("Enter the degree of sine: ");
scanf("%lf", &degree); // Note
printf("Enter the maximum taylor expansion order: ");
scanf("%d", &max_taylor_order);
double rad = degree * M_PI / 180.0; // We have M_PI constant already defined
// instead of using 3.14159265...
// Print double (lf) with 15 decial digits, which is full decimal precision.
printf("sin(x) = %0.15lf\n", sin(rad));
printf("sin_taylor_navie(x) = %0.15lf\n",
sin_taylor_naive(rad, max_taylor_order));
printf("sin_taylor_fma(x) = %0.15lf\n",
sin_taylor_fma(rad, max_taylor_order));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment