File: harmonic.sml

package info (click to toggle)
mlton 20130715-3
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 60,900 kB
  • ctags: 69,386
  • sloc: xml: 34,418; ansic: 17,399; lisp: 2,879; makefile: 1,605; sh: 1,254; pascal: 256; python: 143; asm: 97
file content (75 lines) | stat: -rw-r--r-- 2,733 bytes parent folder | download | duplicates (9)
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
fun die str = (
       print (str ^ "\n");
       raise Overflow
       )

local fun loop (big: IntInf.int, small: IntInf.int): IntInf.int =
             if small = 0
                then big
                else loop (small,
                           IntInf.rem (big, small))
in fun gcd (x: IntInf.int, y: IntInf.int): IntInf.int =
          let val x = IntInf.abs x
              val y = IntInf.abs y
              val (x, y) = if x >= y
                              then (x, y)
                              else (y, x)
          in loop (x, y)
          end
end

fun reduce (num: IntInf.int, den: IntInf.int) : IntInf.int * IntInf.int =
       let val g = gcd (num, den)
           val gs = if den >= 0
                       then g
                       else ~ g
       in if gs = 1
             then (num, den)
          else let val rnum = IntInf.quot (num, gs)
                   val badn = IntInf.rem (num, gs)
                   val rden = IntInf.quot (den, gs)
                   val badd = IntInf.rem (den, gs)
               in if badn <> 0
                  orelse num <> rnum * gs
                  orelse badd <> 0
                  orelse den <> rden * gs
                     then die ("Bad: num " ^ (IntInf.toString num)
                               ^ ", den " ^ (IntInf.toString den)
                               ^ ", gcds " ^ (IntInf.toString gs)
                               ^ ", rnum " ^ (IntInf.toString rnum)
                               ^ ", rden " ^ (IntInf.toString rden)
                               ^ ", badn " ^ (IntInf.toString badn)
                               ^ ", badd " ^ (IntInf.toString badd))
                  else ();
                       (rnum, rden)
               end
       end

fun addrecip (xxx: int, (num: IntInf.int, den: IntInf.int))
             : IntInf.int * IntInf.int =
       let val xxx = IntInf.fromInt xxx
           val xnum = xxx * num + den
           val xden = xxx * den
       in reduce (xnum, xden)
       end

fun printRat (num: IntInf.int, den: IntInf.int): unit =
        print (IntInf.toString num ^ "/" ^ IntInf.toString den ^ "\n")

fun spin (limit: int): IntInf.int * IntInf.int =
       let fun loop (n: int, res: IntInf.int * IntInf.int)
                    : IntInf.int * IntInf.int =
                  if n = limit
                     then res
                  else loop (n + 1,
                             addrecip (n, res))
       in if limit <= 0
             then die "Bad limit"
             else loop (1, (0, 1))
       end

val (n, d) = spin 3000
val _ = printRat (n, d)
val _ = printRat (reduce (n * d * n, d * d * n))
val _ = printRat (reduce (n + 1, d + 1))
val _ = printRat (reduce (n * (d + 1) + d * (n + 1), d * (d + 1)))