summaryrefslogtreecommitdiff
path: root/ratio.c
blob: 70a198a73e4f54599a2ba49bb65b775b0a35e0b7 (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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

typedef unsigned long long num;

typedef struct {bool s; num n; num d} rational;

unsigned int 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 convert_int(int i){ 
	rational r;
	r.d = 1;
	r.n = abs(i);
	if(i >= 0) { r.s=false; } else { r.s=true; }
	return r;
}

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(rational r1, rational r2){ return !(difference(r1,r2).s); }

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 to_double(rational r){
	double i;
	if(r.s) { i=-1.0; } else { i=1.0; }
	return i*((double)r.n)/((double)r.d);
}

bool to_string(char* s,rational r){
	sprintf(s,"%llu / %llu",r.n,r.d);
	return true;
}