File: bigvector.go

package info (click to toggle)
addchain 0.4.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,396 kB
  • sloc: sh: 428; makefile: 10
file content (86 lines) | stat: -rw-r--r-- 1,720 bytes parent folder | download
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
// Package bigvector implements operations on vectors of immutable
// multi-precision integers.
package bigvector

import (
	"math/big"

	"github.com/mmcloughlin/addchain/internal/bigint"
)

// Vector of immutable multi-precision integers.
type Vector interface {
	// Len returns vector length.
	Len() int

	// Idx returns integer at index i. Returned integer must not be written to.
	Idx(i int) *big.Int
}

// New constructs an n-dimensional zero vector.
func New(n int) Vector {
	return make(vector, n)
}

type vector []big.Int

func (v vector) Len() int           { return len(v) }
func (v vector) Idx(i int) *big.Int { return &v[i] }

// NewBasis constructs an n-dimensional basis vector with a 1 in position i.
func NewBasis(n, i int) Vector {
	return basis{n: n, i: i}
}

// Basis implementation saves allocations by returning pre-allocated zero and
// one integers based on the index requested.
var (
	zero = bigint.Zero()
	one  = bigint.One()
)

type basis struct {
	n int
	i int
}

func (b basis) Len() int { return b.n }

func (b basis) Idx(i int) *big.Int {
	switch {
	case i >= b.n:
		panic("bigvector: index out of range")
	case i == b.i:
		return one
	default:
		return zero
	}
}

// Add vectors.
func Add(u, v Vector) Vector {
	assertsamelen(u, v)
	n := u.Len()
	w := make(vector, n)
	for i := 0; i < n; i++ {
		w[i].Add(u.Idx(i), v.Idx(i))
	}
	return w
}

// Lsh left shifts every element of the vector v.
func Lsh(v Vector, s uint) Vector {
	n := v.Len()
	w := make(vector, n)
	for i := 0; i < n; i++ {
		w[i].Lsh(v.Idx(i), s)
	}
	return w
}

// assertsamelen panics if u and v are different lengths.
func assertsamelen(u, v Vector) {
	if u.Len() != v.Len() {
		panic("bigvector: length mismatch")
	}
}