reedsolomon.go raw

   1  package utils
   2  
   3  import (
   4  	"sync"
   5  )
   6  
   7  type ReedSolomonEncoder struct {
   8  	gf        *GaloisField
   9  	polynomes []*GFPoly
  10  	m         *sync.Mutex
  11  }
  12  
  13  func NewReedSolomonEncoder(gf *GaloisField) *ReedSolomonEncoder {
  14  	return &ReedSolomonEncoder{
  15  		gf, []*GFPoly{NewGFPoly(gf, []int{1})}, new(sync.Mutex),
  16  	}
  17  }
  18  
  19  func (rs *ReedSolomonEncoder) getPolynomial(degree int) *GFPoly {
  20  	rs.m.Lock()
  21  	defer rs.m.Unlock()
  22  
  23  	if degree >= len(rs.polynomes) {
  24  		last := rs.polynomes[len(rs.polynomes)-1]
  25  		for d := len(rs.polynomes); d <= degree; d++ {
  26  			next := last.Multiply(NewGFPoly(rs.gf, []int{1, rs.gf.ALogTbl[d-1+rs.gf.Base]}))
  27  			rs.polynomes = append(rs.polynomes, next)
  28  			last = next
  29  		}
  30  	}
  31  	return rs.polynomes[degree]
  32  }
  33  
  34  func (rs *ReedSolomonEncoder) Encode(data []int, eccCount int) []int {
  35  	generator := rs.getPolynomial(eccCount)
  36  	info := NewGFPoly(rs.gf, data)
  37  	info = info.MultByMonominal(eccCount, 1)
  38  	_, remainder := info.Divide(generator)
  39  
  40  	result := make([]int, eccCount)
  41  	numZero := int(eccCount) - len(remainder.Coefficients)
  42  	copy(result[numZero:], remainder.Coefficients)
  43  	return result
  44  }
  45