/
ex_rational.go
125 lines (107 loc) · 3.08 KB
/
ex_rational.go
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
package atoms
import (
"fmt"
"hash/fnv"
"math/big"
"github.com/corywalker/expreduce/expreduce/parser/parens"
"github.com/corywalker/expreduce/pkg/expreduceapi"
)
type Rational struct {
Num *big.Int
Den *big.Int
needsEval bool
}
func (thisRational *Rational) StringForm(
params expreduceapi.ToStringParams,
) string {
if params.Form == "FullForm" {
return fmt.Sprintf(
"Rational[%d, %d]",
thisRational.Num,
thisRational.Den,
)
}
if params.Form == "TeXForm" {
return fmt.Sprintf("\\frac{%d}{%d}", thisRational.Num, thisRational.Den)
}
if parens.NeedsParens("System`Times", params.PreviousHead) {
return fmt.Sprintf("(%d/%d)", thisRational.Num, thisRational.Den)
}
return fmt.Sprintf("%d/%d", thisRational.Num, thisRational.Den)
}
func (thisRational *Rational) IsEqual(other expreduceapi.Ex) string {
otherConv, otherIsRational := other.(*Rational)
if !otherIsRational {
return "EQUAL_FALSE"
}
// Assume rational already simplified
if (thisRational.Num.Cmp(otherConv.Num) != 0) ||
(thisRational.Den.Cmp(otherConv.Den) != 0) {
return "EQUAL_FALSE"
}
return "EQUAL_TRUE"
}
func (thisRational *Rational) DeepCopy() expreduceapi.Ex {
tmpn := big.NewInt(0)
tmpn.Set(thisRational.Num)
tmpd := big.NewInt(0)
tmpd.Set(thisRational.Den)
return &Rational{tmpn, tmpd, thisRational.needsEval}
}
func (thisRational *Rational) Copy() expreduceapi.Ex {
return thisRational.DeepCopy()
}
func (thisRational *Rational) asBigRat() *big.Rat {
res := big.NewRat(1, 1)
return res.SetFrac(thisRational.Num, thisRational.Den)
}
func (thisRational *Rational) NeedsEval() bool {
return thisRational.needsEval
}
func (thisRational *Rational) SetNeedsEval(newVal bool) {
thisRational.needsEval = newVal
}
func NewRational(n *big.Int, d *big.Int) *Rational {
return &Rational{n, d, true}
}
func (thisRational *Rational) Hash() uint64 {
h := fnv.New64a()
h.Write([]byte{90, 82, 214, 51, 52, 7, 7, 33})
nBytes, _ := thisRational.Num.GobEncode()
h.Write(nBytes)
dBytes, _ := thisRational.Den.GobEncode()
h.Write(dBytes)
return h.Sum64()
}
func (thisRational *Rational) asBigFloat() *big.Float {
num := big.NewFloat(0)
den := big.NewFloat(0)
newquo := big.NewFloat(0)
num.SetInt(thisRational.Num)
den.SetInt(thisRational.Den)
newquo.Quo(num, den)
return newquo
}
func (thisRational *Rational) addI(i *Integer) {
tmp := big.NewInt(0)
tmp.Mul(i.Val, thisRational.Den)
thisRational.Num.Add(thisRational.Num, tmp)
}
func (thisRational *Rational) addR(otherR *Rational) {
tmp := big.NewInt(0)
// lastrNum/lastrDen + theratNum/theratDen // Together
tmp.Mul(thisRational.Den, otherR.Num)
thisRational.Den.Mul(thisRational.Den, otherR.Den)
thisRational.Num.Mul(thisRational.Num, otherR.Den)
thisRational.Num.Add(thisRational.Num, tmp)
}
func (thisRational *Rational) mulI(i *Integer) {
thisRational.Num.Mul(thisRational.Num, i.Val)
}
func (thisRational *Rational) MulBigI(i *big.Int) {
thisRational.Num.Mul(thisRational.Num, i)
}
func (thisRational *Rational) mulR(otherR *Rational) {
thisRational.Num.Mul(thisRational.Num, otherR.Num)
thisRational.Den.Mul(thisRational.Den, otherR.Den)
}