#include #include #include #include #include #include typedef unsigned long long num; typedef struct {bool s; num n; num d;} rational; num safe_sum(num n1, num n2){ if(n2 > ULLONG_MAX-n1){ printf("Sum overflow: Adding %llu and %llu\n",n1,n2); exit(1); } else { return n1+n2; } } num safe_product(num n1, num n2){ if(n1 != 0 && n2 > ULLONG_MAX/n1){ printf("Product overflow: Multiplying %llu by %llu\n",n1,n2); exit(1); } else { return n1*n2; } } rational int_to_valuetype(int i){ rational r; r.d = 1; r.n = abs(i); if(i >= 0) { r.s=false; } else { r.s=true; } return r; } unsigned int int_to_exptype(unsigned int i){ return i; } num gcd(num a, num b){ num c; while (b) { c = a % b; a = b; b = c; } return a; } rational cancel(rational r){ num a = gcd(r.n,r.d); rational res = {r.s,r.n/a,r.d/a}; return res; } rational sum(rational r1, rational r2){ num a = gcd(r1.d,r2.d); num r1da = r1.d/a; num r2da = r2.d/a; rational r; r.d = safe_product(r1da,r2.d); num n1 = safe_product(r1.n,r2da); num n2 = safe_product(r2.n,r1da); if(r1.s == r2.s){ r.n = safe_sum(n1,n2); r.s = r1.s; } else { if(n1 >= n2) { r.n = n1 - n2; r.s = r1.s; } else { r.n = n2 - n1; r.s = r2.s; } } return cancel(r); } rational difference(rational r1, rational r2){ r2.s = !r2.s; return sum(r1,r2); } bool is_greater_certainly(rational r1, rational r2){ rational diff = difference(r1,r2); return !diff.s && diff.n > 0; } bool is_greater_possibly(rational r1, rational r2){ return is_greater_certainly(r1,r2); } rational maximum(rational r1, rational r2){ if(is_greater_certainly(r1,r2)) return r1; else return r2; } rational product(rational r1, rational r2){ rational r; rational s1 = {r1.s, r1.n, r2.d}; rational s2 = {r2.s, r2.n, r1.d}; rational t1 = cancel(s1); rational t2 = cancel(s2); r.s = t1.s^t2.s; r.n = safe_product(t1.n,t2.n); r.d = safe_product(t1.d,t2.d); return cancel(r); } rational ratio(rational r1, rational r2){ rational r2i = {r2.s,r2.d,r2.n}; return product(r1,r2i); } rational absolute(rational r){ rational s = {false,r.n,r.d}; return s; } rational power(rational r, unsigned int p){ rational s = {0,1,1}; for(int i = 1; i<= p; i++){ s = product(r,s); } return s; } double inv_exptype_to_double(int r){ return 1.0/((double)r); } double valuetype_to_double(rational r){ double i; if(r.s) { i=-1.0; } else { i=1.0; } return i*((double)r.n)/((double)r.d); } int valuetype_to_string(char* s, rational r){ double f = valuetype_to_double(r); sprintf(s,"%llu / %llu = %f… +/- %6.1e",r.n,r.d,f,f*DBL_EPSILON); return 0; } int valuetype_to_latex(char* s, rational r){ if(r.d == 1) { if(r.n == 0) sprintf(s,"$0$"); else if(r.s) sprintf(s,"$-%lld$",r.n); else if(!r.s) sprintf(s,"$%lld$",r.n); } else{ double f = valuetype_to_double(r); sprintf(s,"$\\frac{%llu}{%llu} = %4.3f\\ldots$",r.n,r.d,f); //sprintf(s,"$\\frac{%llu}{%llu} = %3.2f\\ldots \\pm %1.0e$",r.n,r.d,f,f*DBL_EPSILON); } return 0; } int root_to_string(char* s, rational r, unsigned int p){ double f = pow(valuetype_to_double(r),1.0/p); sprintf(s,"(%llu / %llu)^1/%i = %f… +/- %6.1e",r.n,r.d,p,f,2*DBL_EPSILON*f); return 0; } int root_to_latex(char* s, rational r, unsigned int p){ double f = pow(valuetype_to_double(r),1.0/p); sprintf(s,"$\\bigl(\\frac{%llu}{%llu}\\bigr)^{\\frac1{%i}} = %4.3f\\ldots$",r.n,r.d,p,f); //sprintf(s,"$\\bigl(\\frac{%llu}{%llu}\\bigr)^{\\frac1{%i}} = %3.2f\\ldots \\pm %1.0e$",r.n,r.d,p,f,2*DBL_EPSILON*f); return 0; }