1 | void function(root){
|
2 | "use strict"
|
3 |
|
4 | var numbers = {}
|
5 | , u = require('totemizer')
|
6 | , boo = require('boo')
|
7 | , rational
|
8 | , apply = u.liberate(Function.prototype.apply)
|
9 | ;
|
10 |
|
11 |
|
12 | function checkInput(input){ return (input && input.init === rational.init) ? input : rat(input) }
|
13 |
|
14 | function gcd(a, b){
|
15 | var t;
|
16 | a = Math.abs(a)
|
17 | b = Math.abs(b)
|
18 | while (b > 0) {
|
19 | t = b
|
20 | b = a % b
|
21 | a = t
|
22 | }
|
23 | return a
|
24 | }
|
25 |
|
26 | function lcm(a, b){ return Math.abs(a*b)/gcd(a,b) }
|
27 |
|
28 | function hashify(r){ return r[0]+'/'+r[1] }
|
29 |
|
30 | function display(r){ return ''+r[0]+(r[1]!=1?'/'+r[1]:'') }
|
31 |
|
32 | function val(r){ return r[0]/r[1] }
|
33 |
|
34 | function add(x, y){ return rat(x[0]*y[1]+y[0]*x[1], x[1]*y[1]) }
|
35 |
|
36 | function subtract(x, y){ return rat(x[0]*y[1]-y[0]*x[1], x[1]*y[1]) }
|
37 |
|
38 | function multiply(x, y){ return rat(x[0]*y[0], x[1]*y[1]) }
|
39 |
|
40 | function divide(x, y){ return rat(x[0]*y[1], y[0]*x[1]) }
|
41 |
|
42 | rational = boo.Base.derive({
|
43 | init : function(numerator, denominator){
|
44 | this[0] = numerator
|
45 | this[1] = denominator
|
46 | }
|
47 | , toString : u.enslave(hashify)
|
48 | , display : u.enslave(display)
|
49 |
|
50 | , val : u.enslave(val)
|
51 |
|
52 | , add : u.enslave(add)
|
53 | , plus : u.enslave(add)
|
54 |
|
55 | , subtract : u.enslave(subtract)
|
56 | , minus : u.enslave(subtract)
|
57 | , sub: u.enslave(subtract)
|
58 |
|
59 | , multiply : u.enslave(multiply)
|
60 | , times : u.enslave(multiply)
|
61 | , mul: u.enslave(multiply)
|
62 |
|
63 | , divide : u.enslave(divide)
|
64 | , per : u.enslave(divide)
|
65 | , div: u.enslave(divide)
|
66 |
|
67 | })
|
68 |
|
69 | function rat(numerator, denominator){
|
70 |
|
71 | var index, divisor;
|
72 |
|
73 | if ( ! u.isInt(numerator) ) {
|
74 | throw new Error('invalid argument '+numerator+' ('+(typeof numerator)+')')
|
75 | } else if ( typeof numerator === 'string' ) {
|
76 | numerator = Number(numerator)
|
77 | }
|
78 |
|
79 | if ( ! u.isInt(denominator) ) {
|
80 | denominator = 1
|
81 | } else if ( typeof denominator === 'string' ) {
|
82 | denominator = Number(denominator)
|
83 | }
|
84 |
|
85 | if ( denominator === 0 ) {
|
86 |
|
87 | if ( numerator !== 0 ) numerator = 1
|
88 |
|
89 | } else {
|
90 |
|
91 | divisor = gcd(numerator, denominator)
|
92 | if ( Math.abs(divisor) > 1 ) {
|
93 | numerator = numerator / divisor
|
94 | denominator = denominator / divisor
|
95 | }
|
96 |
|
97 | if ( denominator < 0 ) {
|
98 | numerator *= -1
|
99 | denominator *= -1
|
100 | }
|
101 | }
|
102 |
|
103 | index = hashify([numerator, denominator])
|
104 |
|
105 | if ( numbers[index] === undefined ) {
|
106 | numbers[index] = rational.make(numerator, denominator)
|
107 | }
|
108 |
|
109 | return numbers[index]
|
110 |
|
111 | }
|
112 |
|
113 | rat.checkInput = checkInput
|
114 | rat.gcd = function(a, b){ return rat(gcd(a[0],b[0]), lcm(a[1],b[1])) }
|
115 | rat.lcm = function(a, b){ return rat(lcm(a[0],b[0]), gcd(a[1],b[1])) }
|
116 | rat.add = add
|
117 | rat.div = divide
|
118 | rat.sub = subtract
|
119 | rat.mul = multiply
|
120 |
|
121 | if ( typeof module !== 'undefined' && module.exports ) {
|
122 | module.exports = rat
|
123 | } else {
|
124 | root.factory = rat
|
125 | }
|
126 |
|
127 | }(this)
|