mirror of https://github.com/gogits/gogs.git
Unknwon
8 years ago
7 changed files with 413 additions and 0 deletions
@ -0,0 +1,57 @@
|
||||
// Package utils contain some utilities which are needed to create barcodes
|
||||
package utils |
||||
|
||||
import ( |
||||
"image" |
||||
"image/color" |
||||
|
||||
"github.com/boombuler/barcode" |
||||
) |
||||
|
||||
type base1DCode struct { |
||||
*BitList |
||||
kind string |
||||
content string |
||||
} |
||||
|
||||
type base1DCodeIntCS struct { |
||||
base1DCode |
||||
checksum int |
||||
} |
||||
|
||||
func (c *base1DCode) Content() string { |
||||
return c.content |
||||
} |
||||
|
||||
func (c *base1DCode) Metadata() barcode.Metadata { |
||||
return barcode.Metadata{c.kind, 1} |
||||
} |
||||
|
||||
func (c *base1DCode) ColorModel() color.Model { |
||||
return color.Gray16Model |
||||
} |
||||
|
||||
func (c *base1DCode) Bounds() image.Rectangle { |
||||
return image.Rect(0, 0, c.Len(), 1) |
||||
} |
||||
|
||||
func (c *base1DCode) At(x, y int) color.Color { |
||||
if c.GetBit(x) { |
||||
return color.Black |
||||
} |
||||
return color.White |
||||
} |
||||
|
||||
func (c *base1DCodeIntCS) CheckSum() int { |
||||
return c.checksum |
||||
} |
||||
|
||||
// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList
|
||||
func New1DCodeIntCheckSum(codeKind, content string, bars *BitList, checksum int) barcode.BarcodeIntCS { |
||||
return &base1DCodeIntCS{base1DCode{bars, codeKind, content}, checksum} |
||||
} |
||||
|
||||
// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList
|
||||
func New1DCode(codeKind, content string, bars *BitList) barcode.Barcode { |
||||
return &base1DCode{bars, codeKind, content} |
||||
} |
@ -0,0 +1,119 @@
|
||||
package utils |
||||
|
||||
// BitList is a list that contains bits
|
||||
type BitList struct { |
||||
count int |
||||
data []int32 |
||||
} |
||||
|
||||
// NewBitList returns a new BitList with the given length
|
||||
// all bits are initialize with false
|
||||
func NewBitList(capacity int) *BitList { |
||||
bl := new(BitList) |
||||
bl.count = capacity |
||||
x := 0 |
||||
if capacity%32 != 0 { |
||||
x = 1 |
||||
} |
||||
bl.data = make([]int32, capacity/32+x) |
||||
return bl |
||||
} |
||||
|
||||
// Len returns the number of contained bits
|
||||
func (bl *BitList) Len() int { |
||||
return bl.count |
||||
} |
||||
|
||||
func (bl *BitList) grow() { |
||||
growBy := len(bl.data) |
||||
if growBy < 128 { |
||||
growBy = 128 |
||||
} else if growBy >= 1024 { |
||||
growBy = 1024 |
||||
} |
||||
|
||||
nd := make([]int32, len(bl.data)+growBy) |
||||
copy(nd, bl.data) |
||||
bl.data = nd |
||||
} |
||||
|
||||
// AddBit appends the given bits to the end of the list
|
||||
func (bl *BitList) AddBit(bits ...bool) { |
||||
for _, bit := range bits { |
||||
itmIndex := bl.count / 32 |
||||
for itmIndex >= len(bl.data) { |
||||
bl.grow() |
||||
} |
||||
bl.SetBit(bl.count, bit) |
||||
bl.count++ |
||||
} |
||||
} |
||||
|
||||
// SetBit sets the bit at the given index to the given value
|
||||
func (bl *BitList) SetBit(index int, value bool) { |
||||
itmIndex := index / 32 |
||||
itmBitShift := 31 - (index % 32) |
||||
if value { |
||||
bl.data[itmIndex] = bl.data[itmIndex] | 1<<uint(itmBitShift) |
||||
} else { |
||||
bl.data[itmIndex] = bl.data[itmIndex] & ^(1 << uint(itmBitShift)) |
||||
} |
||||
} |
||||
|
||||
// GetBit returns the bit at the given index
|
||||
func (bl *BitList) GetBit(index int) bool { |
||||
itmIndex := index / 32 |
||||
itmBitShift := 31 - (index % 32) |
||||
return ((bl.data[itmIndex] >> uint(itmBitShift)) & 1) == 1 |
||||
} |
||||
|
||||
// AddByte appends all 8 bits of the given byte to the end of the list
|
||||
func (bl *BitList) AddByte(b byte) { |
||||
for i := 7; i >= 0; i-- { |
||||
bl.AddBit(((b >> uint(i)) & 1) == 1) |
||||
} |
||||
} |
||||
|
||||
// AddBits appends the last (LSB) 'count' bits of 'b' the the end of the list
|
||||
func (bl *BitList) AddBits(b int, count byte) { |
||||
for i := int(count) - 1; i >= 0; i-- { |
||||
bl.AddBit(((b >> uint(i)) & 1) == 1) |
||||
} |
||||
} |
||||
|
||||
// GetBytes returns all bits of the BitList as a []byte
|
||||
func (bl *BitList) GetBytes() []byte { |
||||
len := bl.count >> 3 |
||||
if (bl.count % 8) != 0 { |
||||
len++ |
||||
} |
||||
result := make([]byte, len) |
||||
for i := 0; i < len; i++ { |
||||
shift := (3 - (i % 4)) * 8 |
||||
result[i] = (byte)((bl.data[i/4] >> uint(shift)) & 0xFF) |
||||
} |
||||
return result |
||||
} |
||||
|
||||
// IterateBytes iterates through all bytes contained in the BitList
|
||||
func (bl *BitList) IterateBytes() <-chan byte { |
||||
res := make(chan byte) |
||||
|
||||
go func() { |
||||
c := bl.count |
||||
shift := 24 |
||||
i := 0 |
||||
for c > 0 { |
||||
res <- byte((bl.data[i] >> uint(shift)) & 0xFF) |
||||
shift -= 8 |
||||
if shift < 0 { |
||||
shift = 24 |
||||
i++ |
||||
} |
||||
c -= 8 |
||||
} |
||||
close(res) |
||||
}() |
||||
|
||||
return res |
||||
} |
@ -0,0 +1,65 @@
|
||||
package utils |
||||
|
||||
// GaloisField encapsulates galois field arithmetics
|
||||
type GaloisField struct { |
||||
Size int |
||||
Base int |
||||
ALogTbl []int |
||||
LogTbl []int |
||||
} |
||||
|
||||
// NewGaloisField creates a new galois field
|
||||
func NewGaloisField(pp, fieldSize, b int) *GaloisField { |
||||
result := new(GaloisField) |
||||
|
||||
result.Size = fieldSize |
||||
result.Base = b |
||||
result.ALogTbl = make([]int, fieldSize) |
||||
result.LogTbl = make([]int, fieldSize) |
||||
|
||||
x := 1 |
||||
for i := 0; i < fieldSize; i++ { |
||||
result.ALogTbl[i] = x |
||||
x = x * 2 |
||||
if x >= fieldSize { |
||||
x = (x ^ pp) & (fieldSize - 1) |
||||
} |
||||
} |
||||
|
||||
for i := 0; i < fieldSize; i++ { |
||||
result.LogTbl[result.ALogTbl[i]] = int(i) |
||||
} |
||||
|
||||
return result |
||||
} |
||||
|
||||
func (gf *GaloisField) Zero() *GFPoly { |
||||
return NewGFPoly(gf, []int{0}) |
||||
} |
||||
|
||||
// AddOrSub add or substract two numbers
|
||||
func (gf *GaloisField) AddOrSub(a, b int) int { |
||||
return a ^ b |
||||
} |
||||
|
||||
// Multiply multiplys two numbers
|
||||
func (gf *GaloisField) Multiply(a, b int) int { |
||||
if a == 0 || b == 0 { |
||||
return 0 |
||||
} |
||||
return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%(gf.Size-1)] |
||||
} |
||||
|
||||
// Divide divides two numbers
|
||||
func (gf *GaloisField) Divide(a, b int) int { |
||||
if b == 0 { |
||||
panic("divide by zero") |
||||
} else if a == 0 { |
||||
return 0 |
||||
} |
||||
return gf.ALogTbl[(gf.LogTbl[a]-gf.LogTbl[b])%(gf.Size-1)] |
||||
} |
||||
|
||||
func (gf *GaloisField) Invers(num int) int { |
||||
return gf.ALogTbl[(gf.Size-1)-gf.LogTbl[num]] |
||||
} |
@ -0,0 +1,103 @@
|
||||
package utils |
||||
|
||||
type GFPoly struct { |
||||
gf *GaloisField |
||||
Coefficients []int |
||||
} |
||||
|
||||
func (gp *GFPoly) Degree() int { |
||||
return len(gp.Coefficients) - 1 |
||||
} |
||||
|
||||
func (gp *GFPoly) Zero() bool { |
||||
return gp.Coefficients[0] == 0 |
||||
} |
||||
|
||||
// GetCoefficient returns the coefficient of x ^ degree
|
||||
func (gp *GFPoly) GetCoefficient(degree int) int { |
||||
return gp.Coefficients[gp.Degree()-degree] |
||||
} |
||||
|
||||
func (gp *GFPoly) AddOrSubstract(other *GFPoly) *GFPoly { |
||||
if gp.Zero() { |
||||
return other |
||||
} else if other.Zero() { |
||||
return gp |
||||
} |
||||
smallCoeff := gp.Coefficients |
||||
largeCoeff := other.Coefficients |
||||
if len(smallCoeff) > len(largeCoeff) { |
||||
largeCoeff, smallCoeff = smallCoeff, largeCoeff |
||||
} |
||||
sumDiff := make([]int, len(largeCoeff)) |
||||
lenDiff := len(largeCoeff) - len(smallCoeff) |
||||
copy(sumDiff, largeCoeff[:lenDiff]) |
||||
for i := lenDiff; i < len(largeCoeff); i++ { |
||||
sumDiff[i] = int(gp.gf.AddOrSub(int(smallCoeff[i-lenDiff]), int(largeCoeff[i]))) |
||||
} |
||||
return NewGFPoly(gp.gf, sumDiff) |
||||
} |
||||
|
||||
func (gp *GFPoly) MultByMonominal(degree int, coeff int) *GFPoly { |
||||
if coeff == 0 { |
||||
return gp.gf.Zero() |
||||
} |
||||
size := len(gp.Coefficients) |
||||
result := make([]int, size+degree) |
||||
for i := 0; i < size; i++ { |
||||
result[i] = int(gp.gf.Multiply(int(gp.Coefficients[i]), int(coeff))) |
||||
} |
||||
return NewGFPoly(gp.gf, result) |
||||
} |
||||
|
||||
func (gp *GFPoly) Multiply(other *GFPoly) *GFPoly { |
||||
if gp.Zero() || other.Zero() { |
||||
return gp.gf.Zero() |
||||
} |
||||
aCoeff := gp.Coefficients |
||||
aLen := len(aCoeff) |
||||
bCoeff := other.Coefficients |
||||
bLen := len(bCoeff) |
||||
product := make([]int, aLen+bLen-1) |
||||
for i := 0; i < aLen; i++ { |
||||
ac := int(aCoeff[i]) |
||||
for j := 0; j < bLen; j++ { |
||||
bc := int(bCoeff[j]) |
||||
product[i+j] = int(gp.gf.AddOrSub(int(product[i+j]), gp.gf.Multiply(ac, bc))) |
||||
} |
||||
} |
||||
return NewGFPoly(gp.gf, product) |
||||
} |
||||
|
||||
func (gp *GFPoly) Divide(other *GFPoly) (quotient *GFPoly, remainder *GFPoly) { |
||||
quotient = gp.gf.Zero() |
||||
remainder = gp |
||||
fld := gp.gf |
||||
denomLeadTerm := other.GetCoefficient(other.Degree()) |
||||
inversDenomLeadTerm := fld.Invers(int(denomLeadTerm)) |
||||
for remainder.Degree() >= other.Degree() && !remainder.Zero() { |
||||
degreeDiff := remainder.Degree() - other.Degree() |
||||
scale := int(fld.Multiply(int(remainder.GetCoefficient(remainder.Degree())), inversDenomLeadTerm)) |
||||
term := other.MultByMonominal(degreeDiff, scale) |
||||
itQuot := NewMonominalPoly(fld, degreeDiff, scale) |
||||
quotient = quotient.AddOrSubstract(itQuot) |
||||
remainder = remainder.AddOrSubstract(term) |
||||
} |
||||
return |
||||
} |
||||
|
||||
func NewMonominalPoly(field *GaloisField, degree int, coeff int) *GFPoly { |
||||
if coeff == 0 { |
||||
return field.Zero() |
||||
} |
||||
result := make([]int, degree+1) |
||||
result[0] = coeff |
||||
return NewGFPoly(field, result) |
||||
} |
||||
|
||||
func NewGFPoly(field *GaloisField, coefficients []int) *GFPoly { |
||||
for len(coefficients) > 1 && coefficients[0] == 0 { |
||||
coefficients = coefficients[1:] |
||||
} |
||||
return &GFPoly{field, coefficients} |
||||
} |
@ -0,0 +1,44 @@
|
||||
package utils |
||||
|
||||
import ( |
||||
"sync" |
||||
) |
||||
|
||||
type ReedSolomonEncoder struct { |
||||
gf *GaloisField |
||||
polynomes []*GFPoly |
||||
m *sync.Mutex |
||||
} |
||||
|
||||
func NewReedSolomonEncoder(gf *GaloisField) *ReedSolomonEncoder { |
||||
return &ReedSolomonEncoder{ |
||||
gf, []*GFPoly{NewGFPoly(gf, []int{1})}, new(sync.Mutex), |
||||
} |
||||
} |
||||
|
||||
func (rs *ReedSolomonEncoder) getPolynomial(degree int) *GFPoly { |
||||
rs.m.Lock() |
||||
defer rs.m.Unlock() |
||||
|
||||
if degree >= len(rs.polynomes) { |
||||
last := rs.polynomes[len(rs.polynomes)-1] |
||||
for d := len(rs.polynomes); d <= degree; d++ { |
||||
next := last.Multiply(NewGFPoly(rs.gf, []int{1, rs.gf.ALogTbl[d-1+rs.gf.Base]})) |
||||
rs.polynomes = append(rs.polynomes, next) |
||||
last = next |
||||
} |
||||
} |
||||
return rs.polynomes[degree] |
||||
} |
||||
|
||||
func (rs *ReedSolomonEncoder) Encode(data []int, eccCount int) []int { |
||||
generator := rs.getPolynomial(eccCount) |
||||
info := NewGFPoly(rs.gf, data) |
||||
info = info.MultByMonominal(eccCount, 1) |
||||
_, remainder := info.Divide(generator) |
||||
|
||||
result := make([]int, eccCount) |
||||
numZero := int(eccCount) - len(remainder.Coefficients) |
||||
copy(result[numZero:], remainder.Coefficients) |
||||
return result |
||||
} |
@ -0,0 +1,19 @@
|
||||
package utils |
||||
|
||||
// RuneToInt converts a rune between '0' and '9' to an integer between 0 and 9
|
||||
// If the rune is outside of this range -1 is returned.
|
||||
func RuneToInt(r rune) int { |
||||
if r >= '0' && r <= '9' { |
||||
return int(r - '0') |
||||
} |
||||
return -1 |
||||
} |
||||
|
||||
// IntToRune converts a digit 0 - 9 to the rune '0' - '9'. If the given int is outside
|
||||
// of this range 'F' is returned!
|
||||
func IntToRune(i int) rune { |
||||
if i >= 0 && i <= 9 { |
||||
return rune(i + '0') |
||||
} |
||||
return 'F' |
||||
} |
Loading…
Reference in new issue