-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpeano.ml
110 lines (94 loc) · 2.17 KB
/
peano.ml
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
type p =
Z |
S of p |
D of p
let dec (x:p) : p =
match x with
| Z -> D Z
| S i -> i
| x -> D x
let n (x:int) : p =
let rec aux acc = function
| 0 -> acc
| x ->
if x > 0
then aux (S acc) (x - 1)
else aux (D acc) (x + 1)
in
aux Z x
let to_int (n:p) : int =
let rec aux acc = function
| Z -> acc
| S n -> aux (acc + 1) n
| D n -> aux (acc - 1) n
in
aux 0 n
let repr (n:p) : string =
let rec aux count p =
match p with
| Z -> "Z"
| S p' -> if count >= 10
then "..."
else "S(" ^ aux (count + 1) p' ^ ")"
| D p' -> if count >= 10
then "..."
else "D(" ^ aux (count + 1) p' ^ ")"
in aux 0 n
let ( + ) (x:p) (y:p) : p =
let rec aux acc = function
| Z -> acc
| S y -> aux (S acc) y
| D y -> aux (dec acc) y
in
aux x y
let ( - ) (x:p) (y:p) : p =
let rec aux acc = function
| Z -> acc
| S y -> aux (dec acc) y
| D y -> aux (S acc) y
in
aux x y
let ( * ) (x:p) (y:p) : p =
let rec aux acc = function
| Z -> acc
| S y -> aux (acc + x) y
| D y -> aux (acc - x) y
in
aux Z y
let ( ^ ) (x:p) (y:p) : p =
let rec aux acc = function
| Z -> acc
| S y -> aux (acc * x) y
| D _ -> failwith "negative exponent in ( ^ ) fn"
in
aux (S Z) y
let ( <= ) (x:p) (y:p) : bool =
match x - y with
| Z | D _ -> true
| S _ -> false
let ( >= ) = (fun f x y -> f y x) ( <= )
let make_pos (x:p) : p =
match x with
| Z | S _ -> x
| D _ -> (D Z) * x
let ( / ) (x:p) (y:p) : p =
let sign = match x, y with
| D _, S _ | S _, D _ -> D Z
| _ -> S Z
in
let x = make_pos x in
let y = make_pos y in
let rec aux acc x =
if x - (dec y) <= Z
then acc
else aux (S acc) (x - y)
in aux Z x * sign
let ( % ) (x:p) (y:p) : p =
let rec aux acc n =
if acc - (dec y) <= Z
then acc
else aux (acc - y) (dec n)
in
if x >= Z && y >= Z
then aux x y
else Z