aboutsummaryrefslogtreecommitdiff
path: root/ops.go
blob: 7d35e0d99d345e67fd669a7bd60e582c0cef606b (plain)
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
package main

import (
	"container/list"
	"fmt"
	"log"
)

type (
	// Set is ordered set of alphabet
	Set struct{ *list.List }

	// Element of ordered set
	Element struct{ *list.Element }
)

var (
	alphabet  Set
	zero, one Element
)

func init() {
	alphabet = Set{list.New()}
	for i := 0; i <= maxValue; i++ {
		alphabet.PushBack(i)
	}
	zero = Element{alphabet.Front()}
	one = Element{zero.Next()}
}

func (m Element) next() Element {
	if nxt := m.Next(); nxt != nil {
		return Element{nxt}
	}
	log.Fatal("out of range ", m)
	return Element{}
}

func (m Element) prev() Element {
	if prv := m.Prev(); prv != nil {
		return Element{prv}
	}
	return zero
}

// Add defines addition
func Add(m, n Element) Element { return m.add(n) }

func (m Element) add(n Element) Element {
	if m == zero {
		return n
	}
	return m.prev().add(n).next()
}

// Mul defines mutiplication
func Mul(m, n Element) Element { return m.mul(n) }

func (m Element) mul(n Element) Element {
	if m == zero {
		return zero
	}
	return m.prev().mul(n).add(n)
}

// Pow defines power function
func Pow(m, n Element) Element { return m.pow(n) }

func (m Element) pow(n Element) Element {
	if n == zero {
		return one
	}
	return m.pow(n.prev()).mul(m)
}

// Sub defines substraction
func Sub(m, n Element) Element { return m.sub(n) }

func (m Element) sub(n Element) Element {
	if n == zero {
		return m
	}
	return m.sub(n.prev()).prev()
}

// Equals compares two elements
func (m Element) Equals(n Element) bool {
	return m.Value == n.Value
}

// String pretty-prints value
func (m Element) String() string {
	return fmt.Sprint(m.Value)
}

// Index returns n-th Element
func Index(n int) Element {
	if n > alphabet.Len() {
		log.Fatal("out of range ", n)
		return Element{}
	}
	e := alphabet.Front()
	for i := 0; i < n; i++ {
		e = e.Next()
	}
	return Element{e}
}