github.com/cloudflare/circl@v1.5.0/math/mlsbset/power.go (about)

     1  package mlsbset
     2  
     3  import "fmt"
     4  
     5  // Power is a valid exponent produced by the MLSBSet encoding algorithm.
     6  type Power struct {
     7  	set Encoder // parameters of code.
     8  	s   []int32 // set of signs.
     9  	b   []int32 // set of digits.
    10  	c   int     // carry is {0,1}.
    11  }
    12  
    13  // Exp is calculates x^k, where x is a predetermined element of a group G.
    14  func (p *Power) Exp(G Group) EltG {
    15  	a, b := G.Identity(), G.NewEltP()
    16  	for e := int(p.set.p.E - 1); e >= 0; e-- {
    17  		G.Sqr(a)
    18  		for v := uint(0); v < p.set.p.V; v++ {
    19  			sgnElt, idElt := p.Digit(v, uint(e))
    20  			G.Lookup(b, v, sgnElt, idElt)
    21  			G.Mul(a, b)
    22  		}
    23  	}
    24  	if p.set.IsExtended() && p.c == 1 {
    25  		G.Mul(a, G.ExtendedEltP())
    26  	}
    27  	return a
    28  }
    29  
    30  // Digit returns the (v,e)-th digit and its sign.
    31  func (p *Power) Digit(v, e uint) (sgn, dig int32) {
    32  	sgn = p.bit(0, v, e)
    33  	dig = 0
    34  	for i := p.set.p.W - 1; i > 0; i-- {
    35  		dig = 2*dig + p.bit(i, v, e)
    36  	}
    37  	mask := dig >> 31
    38  	dig = (dig + mask) ^ mask
    39  	return sgn, dig
    40  }
    41  
    42  // bit returns the (w,v,e)-th bit of the code.
    43  func (p *Power) bit(w, v, e uint) int32 {
    44  	if !(w < p.set.p.W &&
    45  		v < p.set.p.V &&
    46  		e < p.set.p.E) {
    47  		panic(fmt.Errorf("indexes outside (%v,%v,%v)", w, v, e))
    48  	}
    49  	if w == 0 {
    50  		return p.s[p.set.p.E*v+e]
    51  	}
    52  	return p.b[p.set.p.D*(w-1)+p.set.p.E*v+e]
    53  }
    54  
    55  func (p *Power) String() string {
    56  	dig := ""
    57  	for j := uint(0); j < p.set.p.V; j++ {
    58  		for i := uint(0); i < p.set.p.E; i++ {
    59  			s, d := p.Digit(j, i)
    60  			dig += fmt.Sprintf("(%2v,%2v) = %+2v %+2v\n", j, i, s, d)
    61  		}
    62  	}
    63  	return fmt.Sprintf("len: %v\ncarry: %v\ndigits:\n%v", len(p.b)+len(p.s), p.c, dig)
    64  }