-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconvert.go
97 lines (78 loc) · 1.94 KB
/
convert.go
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
// Package radix implements radix conversions for integer sequences ([]byte or []int)
// and their encoding/deconding to string by specified alphabet.
package radix
import (
"errors"
"fmt"
"math"
"math/big"
)
// Convert converts input (int) with radix (inrx) to ouput (out) with radix (outrx).
func Convert(in []int, inrx int, outrx int) (out []int, err error) {
if inrx < 2 {
return nil, errors.New("inrx must be greater than 1")
}
if outrx < 2 {
return nil, errors.New("outrx must be greater than 1")
}
if len(in) == 0 {
return
}
outlen := int(math.Ceil(float64(len(in)) * math.Log(float64(inrx)) / math.Log(float64(outrx))))
out = make([]int, outlen)
outlen = 0
for ini, inv := range in {
if inv >= inrx {
return nil, fmt.Errorf("in[%v]: %v must be less than inrx: %v", ini, inv, inrx)
}
if inv < 0 {
return nil, fmt.Errorf("in[%v]: %v must be greater or equal 0", ini, inv)
}
carry := inv
outi := 0
for outi < outlen || carry > 0 {
outv := out[outi]
if outv > 0 {
outv = outv*inrx + carry
} else {
outv = carry
}
carry = outv / outrx
out[outi] = outv % outrx
outi++
}
if outi > outlen {
outlen = outi
}
}
out = out[:outlen]
for i, j := 0, len(out)-1; i < j; i, j = i+1, j-1 {
out[i], out[j] = out[j], out[i]
}
return
}
// ConvertBytes converts input bytes (in) with 256 radix
// to output bytes (out) with radix (outrx).
func ConvertBytes(in []byte, outrx int) (out []byte, err error) {
if outrx < 2 {
return nil, errors.New("outrx must be greater than 1")
}
if outrx > 256 {
return nil, errors.New("outrx must be less than 256")
}
if len(in) == 0 {
return
}
rx := big.NewInt(int64(outrx))
zero := big.NewInt(0)
num := new(big.Int).SetBytes(in)
for num.Cmp(zero) != 0 {
mod := new(big.Int)
num.DivMod(num, rx, mod)
out = append(out, byte(mod.Int64()))
}
for i, j := 0, len(out)-1; i < j; i, j = i+1, j-1 {
out[i], out[j] = out[j], out[i]
}
return
}