-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathRational.js
72 lines (63 loc) · 2.25 KB
/
Rational.js
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
// Rational.js
// (c) 2009 B. Crowell and M. Khafateh, GPL 2 license
//
// This file provides a constructor, com.lightandmatter.Rational.
//
var com;
if (!com) {com = {};}
if (!com.lightandmatter) {com.lightandmatter = {};}
com.lightandmatter.Rational =
function (x,y,notidy) {
var c = {};
c.x = x; // top; can be negative
c.y = y; // bottom; supposed to be positive, but we'll fix it if it isn't
// At the very end, after all the methods are defined, we tidy this.
c.mytype = 'q';
c.clone = function (notidy) {return com.lightandmatter.Rational(c.x,c.y,notidy); };
c.to_array = function () {return [c.x,c.y];};
c.eq = function (b) {return c.x!==null && c.y!==null && c.x*b.y==c.y*b.x; };
c.cmp = function (b) {
if (c.x===null || c.y===null) {return null;}
return c.x*b.y-b.x*c.y; // works because y's are guaranteed positive
};
c.mul = function (b) { return com.lightandmatter.Rational(c.x*b.x,c.y*b.y); };
c.div = function (b) { if (b.x===0) {return NaN;} return com.lightandmatter.Rational(c.x*b.y,c.y*b.x); };
c.neg = function () { return com.lightandmatter.Rational(-c.x,c.y); };
c.abs = function () { return com.lightandmatter.Rational(Math.abs(c.x),c.y); };
c.add = function (b) { return com.lightandmatter.Rational(c.x*b.y+b.x*c.y,c.y*b.y); };
c.sub = function (b) { return c.add(b.neg()); };
c.toString = function() {
if (c.y==1) {return c.x.toString();}
return c.x + '/' + c.y;
};
c.toNumber = function() {
return c.x/c.y;
};
c.tidy = function() { // returns result, doesn't operate in place; may return native number type
if (c.y==1) {return c.x;}
if (c.x===0) {return 0;}
var j = c.clone(true);
j.x = c.x;
j.y = c.y;
if (j.y<0) {j.x= -j.x; j.y= -j.y;}
// mod operator messes up on negatives, so temporarily force positive:
var s = 1;
if (j.x<0) {
s= -1;
j.x= -j.x;
}
var n = j.x;
var d = j.y;
var gcd = function(a,b) {
if (b>a) {var foo=a; a=b; b=foo;}
while (a%b>0) {var foo=b; b=a%b; a=foo;}
return b;
};
var g = gcd(n,d);
j.x = s*n/g;
j.y = d/g;
return j;
};
if (!notidy) {c=c.tidy();}
return c;
};