summaryrefslogtreecommitdiffstats log msg author committer range
path: root/src/continued-fraction.c
blob: 5aa7a4fd103309ae9323b13d3bfc0098b9303b48 (plain)
 ```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 ``` ``````#ifdef HAVE_CONFIG_H #include #endif /* * Stolen from gnumeric * * Original code from Morten Welinder */ #include #include #include "continued-fraction.h" void sa_continued_fraction(double val, int max_denom, int *res_num, int *res_denom) { int n1, n2, d1, d2; double x, y; if (val < 0) { sa_continued_fraction (-val, max_denom, res_num, res_denom); *res_num = -*res_num; return; } n1 = 0; d1 = 1; n2 = 1; d2 = 0; x = val; y = 1; do { int a = (int) (x / y); double newy = x - a * y; int n3, d3; if ((n2 && a > (INT_MAX - n1) / n2) || (d2 && a > (INT_MAX - d1) / d2) || a * d2 + d1 > max_denom) { *res_num = n2; *res_denom = d2; return; } n3 = a * n2 + n1; d3 = a * d2 + d1; x = y; y = newy; n1 = n2; n2 = n3; d1 = d2; d2 = d3; } while (y > 1e-10); *res_num = n2; *res_denom = d2; } #if 0 int main(int argc, char*argv[]) { float value = 3.1417235; int res_num, res_denom; sa_continued_fraction(value, 0xFFFF, &res_num, &res_denom); printf("%g ~= %i/%i = %g\n", value, res_num, res_denom, (float) res_num / res_denom); return 0; } #endif ``````