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

import (
	"container/list"
	"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)
}

// Pot defines power function
func Pot(m, n Element) Element { return m.pot(n) }

func (m Element) pot(n Element) Element {
	if n == zero {
		return one
	}
	return m.pot(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()
}