Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a9db1b8

Browse files
committedJun 24, 2020
initial draft for Rational support
1 parent 6e5868a commit a9db1b8

File tree

1 file changed

+222
-0
lines changed

1 file changed

+222
-0
lines changed
 
+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
package singleton.ops
2+
3+
import singleton.ops._
4+
import singleton.ops.impl.{OpCast, OpGen, OpInt, OpMacro}
5+
6+
object rational {
7+
/** Represents a rational number
8+
*
9+
* @tparam N the numerator
10+
* @tparam D the denominator
11+
*/
12+
trait Rational[N, D] {
13+
// currently only XInt is supported,
14+
// other types such as XLong could be added with additional implicit rules
15+
def n(implicit nv: Id[N]): nv.Out = nv.value
16+
def d(implicit dv: Id[D]): dv.Out = dv.value
17+
def show(implicit nv: Id[N], dv: Id[D]): String = s"Rational(${n}, ${d})"
18+
}
19+
20+
private trait IsRationalImpl[P] {
21+
type Out
22+
}
23+
private trait IsRationalImplDefault {
24+
type Aux[P, O] = IsRationalImpl[P] { type Out = O }
25+
implicit def isRationalFalse[P]: Aux[P, false] =
26+
new IsRationalImpl[P] {
27+
type Out = false
28+
}
29+
}
30+
private object IsRationalImpl extends IsRationalImplDefault {
31+
implicit def isRationalTrue[N, D]: Aux[Rational[N, D], true] =
32+
new IsRationalImpl[Rational[N, D]] {
33+
type Out = true
34+
}
35+
}
36+
37+
trait IsRationalOpId
38+
type IsRational[P] = OpMacro[IsRationalOpId, P, W.`0`.T, W.`0`.T]
39+
40+
implicit def doIsRational[P, T](implicit
41+
tst: IsRationalImpl.Aux[P, T]): OpIntercept.Aux[IsRational[P], T] = ???
42+
43+
trait ToRationalOpId
44+
type ToRational[P] = OpMacro[ToRationalOpId, P, W.`0`.T, W.`0`.T]
45+
46+
implicit def toRationalFromRat[
47+
N <: XInt, D <: XInt,
48+
SN <: XInt, SD <: XInt](
49+
implicit
50+
sim: OpGen.Aux[Simplify[Rational[N, D]], Rational[SN, SD]]
51+
): OpIntercept.Aux[ToRational[Rational[N, D]], Rational[SN, SD]] =
52+
new OpIntercept[ToRational[Rational[N, D]]] {
53+
type Out = Rational[SN, SD]
54+
val value: Out = new Rational[SN, SD] {}
55+
}
56+
57+
implicit def toRationalFromInt[N <: XInt]: OpIntercept.Aux[ToRational[N], Rational[N, W.`1`.T]] =
58+
new OpIntercept[ToRational[N]] {
59+
type Out = Rational[N, W.`1`.T]
60+
val value: Out = new Rational[N, W.`1`.T] {}
61+
}
62+
63+
implicit def doRationalNegate[N <: XInt, D <: XInt, NN <: XInt](implicit
64+
neg: OpInt.Aux[Negate[N], NN]): OpIntercept.Aux[Negate[Rational[N, D]], Rational[NN, D]] =
65+
new OpIntercept[Negate[Rational[N, D]]] {
66+
type Out = Rational[NN, D]
67+
val value: Out = new Rational[NN, D] {}
68+
}
69+
70+
implicit def doRationalAdd[
71+
LHS, RHS,
72+
LN <: XInt, LD <: XInt,
73+
RN <: XInt, RD <: XInt,
74+
LNRD <: XInt, RNLD <: XInt,
75+
N <: XInt, D <: XInt,
76+
SN <: XInt, SD <: XInt](
77+
implicit
78+
rat: Require[IsRational[LHS] || IsRational[RHS]],
79+
lhs: OpGen.Aux[ToRational[LHS], Rational[LN, LD]],
80+
rhs: OpGen.Aux[ToRational[RHS], Rational[RN, RD]],
81+
ev0: OpInt.Aux[LN * RD, LNRD],
82+
ev1: OpInt.Aux[RN * LD, RNLD],
83+
ev2: OpInt.Aux[LNRD + RNLD, N],
84+
ev3: OpInt.Aux[LD * RD, D],
85+
ev4: OpGen.Aux[Simplify[Rational[N, D]], Rational[SN, SD]],
86+
): OpIntercept.Aux[LHS + RHS, Rational[SN, SD]] =
87+
new OpIntercept[LHS + RHS] {
88+
type Out = Rational[SN, SD]
89+
val value: Out = new Rational[SN, SD] {}
90+
}
91+
92+
implicit def doRationalSubtract[
93+
LHS, RHS,
94+
LN <: XInt, LD <: XInt,
95+
RN <: XInt, RD <: XInt, RNN <: XInt,
96+
SN <: XInt, SD <: XInt](
97+
implicit
98+
rat: Require[IsRational[LHS] || IsRational[RHS]],
99+
lhs: OpGen.Aux[ToRational[LHS], Rational[LN, LD]],
100+
rhs: OpGen.Aux[ToRational[RHS], Rational[RN, RD]],
101+
neg: OpInt.Aux[Negate[RN], RNN],
102+
add: OpGen.Aux[Rational[LN, LD] + Rational[RNN, RD], Rational[SN, SD]]
103+
): OpIntercept.Aux[LHS - RHS, Rational[SN, SD]] =
104+
new OpIntercept[LHS - RHS] {
105+
type Out = Rational[SN, SD]
106+
val value: Out = new Rational[SN, SD] {}
107+
}
108+
109+
implicit def doRationalMultiply[
110+
LHS, RHS,
111+
LN <: XInt, LD <: XInt,
112+
RN <: XInt, RD <: XInt,
113+
N <: XInt, D <: XInt,
114+
SN <: XInt, SD <: XInt](
115+
implicit
116+
rat: Require[IsRational[LHS] || IsRational[RHS]],
117+
lhs: OpGen.Aux[ToRational[LHS], Rational[LN, LD]],
118+
rhs: OpGen.Aux[ToRational[RHS], Rational[RN, RD]],
119+
ev0: OpInt.Aux[LN * RN, N],
120+
ev1: OpInt.Aux[LD * RD, D],
121+
ev2: OpGen.Aux[Simplify[Rational[N, D]], Rational[SN, SD]]
122+
): OpIntercept.Aux[LHS * RHS, Rational[SN, SD]] =
123+
new OpIntercept[LHS * RHS] {
124+
type Out = Rational[SN, SD]
125+
val value: Out = new Rational[SN, SD] {}
126+
}
127+
128+
implicit def doRationalDivide[
129+
LHS, RHS,
130+
LN <: XInt, LD <: XInt,
131+
RN <: XInt, RD <: XInt,
132+
SN <: XInt, SD <: XInt](
133+
implicit
134+
rat: Require[IsRational[LHS] || IsRational[RHS]],
135+
lhs: OpGen.Aux[ToRational[LHS], Rational[LN, LD]],
136+
rhs: OpGen.Aux[ToRational[RHS], Rational[RN, RD]],
137+
mul: OpGen.Aux[Rational[LN, LD] * Rational[RD, RN], Rational[SN, SD]]
138+
): OpIntercept.Aux[LHS / RHS, Rational[SN, SD]] =
139+
new OpIntercept[LHS / RHS] {
140+
type Out = Rational[SN, SD]
141+
val value: Out = new Rational[SN, SD] {}
142+
}
143+
144+
trait GCDOpId
145+
type GCD[A, B] = OpMacro[GCDOpId, A, B, W.`0`.T]
146+
147+
private type gcdErrorMsg = W.`"GCD requires positive integers"`.T
148+
149+
implicit def doGCDforBasisCase[A <: XInt, B <: XInt, Rem <: XInt](implicit
150+
ev0: RequireMsg[(A >= B) && (B > W.`0`.T), gcdErrorMsg],
151+
ev1: OpInt.Aux[A % B, Rem],
152+
ev2: Require[Rem == W.`0`.T]): OpIntercept.Aux[GCD[A, B], B] = ???
153+
154+
implicit def doGCDforAgeB[A <: XInt, B <: XInt,Rem <: XInt, D <: XInt](implicit
155+
ev0: RequireMsg[(A >= B) && (B > W.`0`.T), gcdErrorMsg],
156+
ev1: OpInt.Aux[A % B, Rem],
157+
ev2: Require[Rem != W.`0`.T],
158+
ev3: OpInt.Aux[GCD[B, Rem], D]): OpIntercept.Aux[GCD[A, B], D] = ???
159+
160+
implicit def doGCDforAltB[A <: XInt, B <: XInt, Rem <: XInt, D <: XInt](implicit
161+
ev0: RequireMsg[(A < B) && (A > W.`0`.T), gcdErrorMsg],
162+
ev1: OpInt.Aux[GCD[B, A], D]): OpIntercept.Aux[GCD[A, B], D] = ???
163+
164+
trait SimplifyOpId
165+
type Simplify[F] = OpMacro[SimplifyOpId, F, W.`0`.T, W.`0`.T]
166+
167+
private type simplifyErrorMsg = W.`"Simplify requires non-zero denominator"`.T
168+
169+
implicit def doSimplifyPositive[
170+
N <: XInt, D <: XInt,
171+
C <: XInt,
172+
SN <: XInt, SD <: XInt](
173+
implicit
174+
ev0: RequireMsg[(N > W.`0`.T) && (D > W.`0`.T), simplifyErrorMsg],
175+
gcd: OpInt.Aux[GCD[N, D], C],
176+
n: OpInt.Aux[N / C, SN],
177+
d: OpInt.Aux[D / C, SD]
178+
): OpIntercept.Aux[Simplify[Rational[N, D]], Rational[SN, SD]] =
179+
new OpIntercept[Simplify[Rational[N, D]]] {
180+
type Out = Rational[SN, SD]
181+
val value = new Rational[SN, SD] {}
182+
}
183+
184+
implicit def doSimplifyNegative[
185+
N <: XInt, D <: XInt,
186+
F <: Rational[_, _],
187+
SNF <: Rational[_, _],
188+
SN <: XInt, SD <: XInt](
189+
implicit
190+
ev0: RequireMsg[(N < W.`0`.T) && (D > W.`0`.T), simplifyErrorMsg],
191+
ev1: OpGen.Aux[Negate[Rational[N, D]], F],
192+
ev2: OpGen.Aux[Simplify[F], SNF],
193+
ev3: OpGen.Aux[Negate[SNF], Rational[SN, SD]]
194+
): OpIntercept.Aux[Simplify[Rational[N, D]], Rational[SN, SD]] =
195+
new OpIntercept[Simplify[Rational[N, D]]] {
196+
type Out = Rational[SN, SD]
197+
val value = new Rational[SN, SD] {}
198+
}
199+
200+
implicit def doSimplifyZero[D <: XInt](implicit
201+
nz: RequireMsg[D > W.`0`.T, simplifyErrorMsg]
202+
): OpIntercept.Aux[Simplify[Rational[W.`0`.T, D]], Rational[W.`0`.T, W.`1`.T]] =
203+
new OpIntercept[Simplify[Rational[W.`0`.T, D]]] {
204+
type Out = Rational[W.`0`.T, W.`1`.T]
205+
val value = new Rational[W.`0`.T, W.`1`.T] {}
206+
}
207+
208+
implicit def doSimplifyNegDenom[
209+
N <: XInt, D <: XInt,
210+
NN <: XInt, ND <: XInt,
211+
SN <: XInt, SD <: XInt](
212+
implicit
213+
bn: RequireMsg[D < W.`0`.T, simplifyErrorMsg],
214+
nn: OpInt.Aux[Negate[N], NN],
215+
nd: OpInt.Aux[Negate[D], ND],
216+
sf: OpGen.Aux[Simplify[Rational[NN, ND]], Rational[SN, SD]]
217+
): OpIntercept.Aux[Simplify[Rational[N, D]], Rational[SN, SD]] =
218+
new OpIntercept[Simplify[Rational[N, D]]] {
219+
type Out = Rational[SN, SD]
220+
val value = new Rational[SN, SD] {}
221+
}
222+
}

0 commit comments

Comments
 (0)
Please sign in to comment.