Skip to content

Commit 5c2eb33

Browse files
committed
Tnaf perf. opts.
1 parent 3303aca commit 5c2eb33

File tree

1 file changed

+81
-49
lines changed
  • core/src/main/java/org/bouncycastle/math/ec

1 file changed

+81
-49
lines changed

core/src/main/java/org/bouncycastle/math/ec/Tnaf.java

Lines changed: 81 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import java.math.BigInteger;
44

5+
import org.bouncycastle.util.BigIntegers;
6+
57
/**
68
* Class holding methods for point multiplication based on the window
79
* τ-adic nonadjacent form (WTNAF). The algorithms are based on the
@@ -31,12 +33,16 @@ class Tnaf
3133
* The <code>&alpha;<sub>u</sub></code>'s for <code>a=0</code> as an array
3234
* of <code>ZTauElement</code>s.
3335
*/
34-
public static final ZTauElement[] alpha0 = {
35-
null,
36-
new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
37-
new ZTauElement(MINUS_THREE, MINUS_ONE), null,
38-
new ZTauElement(MINUS_ONE, MINUS_ONE), null,
39-
new ZTauElement(ECConstants.ONE, MINUS_ONE), null
36+
public static final ZTauElement[] alpha0 =
37+
{
38+
null, new ZTauElement(ECConstants.ONE, ECConstants.ZERO),
39+
null, new ZTauElement(MINUS_THREE, MINUS_ONE),
40+
null, new ZTauElement(MINUS_ONE, MINUS_ONE),
41+
null, new ZTauElement(ECConstants.ONE, MINUS_ONE),
42+
null, new ZTauElement(MINUS_ONE, ECConstants.ONE),
43+
null, new ZTauElement(ECConstants.ONE, ECConstants.ONE),
44+
null, new ZTauElement(ECConstants.THREE, ECConstants.ONE),
45+
null, new ZTauElement(MINUS_ONE, ECConstants.ZERO),
4046
};
4147

4248
/**
@@ -51,11 +57,16 @@ class Tnaf
5157
* The <code>&alpha;<sub>u</sub></code>'s for <code>a=1</code> as an array
5258
* of <code>ZTauElement</code>s.
5359
*/
54-
public static final ZTauElement[] alpha1 = {null,
55-
new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null,
56-
new ZTauElement(MINUS_THREE, ECConstants.ONE), null,
57-
new ZTauElement(MINUS_ONE, ECConstants.ONE), null,
58-
new ZTauElement(ECConstants.ONE, ECConstants.ONE), null
60+
public static final ZTauElement[] alpha1 =
61+
{
62+
null, new ZTauElement(ECConstants.ONE, ECConstants.ZERO),
63+
null, new ZTauElement(MINUS_THREE, ECConstants.ONE),
64+
null, new ZTauElement(MINUS_ONE, ECConstants.ONE),
65+
null, new ZTauElement(ECConstants.ONE, ECConstants.ONE),
66+
null, new ZTauElement(MINUS_ONE, MINUS_ONE),
67+
null, new ZTauElement(ECConstants.ONE, MINUS_ONE),
68+
null, new ZTauElement(ECConstants.THREE, MINUS_ONE),
69+
null, new ZTauElement(MINUS_ONE, ECConstants.ZERO),
5970
};
6071

6172
/**
@@ -76,31 +87,29 @@ class Tnaf
7687
*/
7788
public static BigInteger norm(final byte mu, ZTauElement lambda)
7889
{
79-
BigInteger norm;
80-
8190
// s1 = u^2
8291
BigInteger s1 = lambda.u.multiply(lambda.u);
8392

8493
// s2 = u * v
85-
BigInteger s2 = lambda.u.multiply(lambda.v);
94+
// BigInteger s2 = lambda.u.multiply(lambda.v);
8695

8796
// s3 = 2 * v^2
88-
BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1);
97+
// BigInteger s3 = lambda.v.multiply(lambda.v).shiftLeft(1);
8998

9099
if (mu == 1)
91100
{
92-
norm = s1.add(s2).add(s3);
101+
// return s1.add(s2).add(s3);
102+
return lambda.v.shiftLeft(1).add(lambda.u).multiply(lambda.v).add(s1);
93103
}
94104
else if (mu == -1)
95105
{
96-
norm = s1.subtract(s2).add(s3);
106+
// return s1.subtract(s2).add(s3);
107+
return lambda.v.shiftLeft(1).subtract(lambda.u).multiply(lambda.v).add(s1);
97108
}
98109
else
99110
{
100111
throw new IllegalArgumentException("mu must be 1 or -1");
101112
}
102-
103-
return norm;
104113
}
105114

106115
/**
@@ -650,10 +659,11 @@ public static ECPoint.AbstractF2m multiplyRTnaf(ECPoint.AbstractF2m p, BigIntege
650659
public static ECPoint.AbstractF2m multiplyTnaf(ECPoint.AbstractF2m p, ZTauElement lambda)
651660
{
652661
ECCurve.AbstractF2m curve = (ECCurve.AbstractF2m)p.getCurve();
662+
ECPoint.AbstractF2m pNeg = (ECPoint.AbstractF2m)p.negate();
653663
byte mu = getMu(curve.getA());
654664
byte[] u = tauAdicNaf(mu, lambda);
655665

656-
return multiplyFromTnaf(p, u);
666+
return multiplyFromTnaf(p, pNeg, u);
657667
}
658668

659669
/**
@@ -665,11 +675,10 @@ public static ECPoint.AbstractF2m multiplyTnaf(ECPoint.AbstractF2m p, ZTauElemen
665675
* @param u The the TNAF of <code>&lambda;</code>..
666676
* @return <code>&lambda; * p</code>
667677
*/
668-
public static ECPoint.AbstractF2m multiplyFromTnaf(ECPoint.AbstractF2m p, byte[] u)
678+
public static ECPoint.AbstractF2m multiplyFromTnaf(ECPoint.AbstractF2m p, ECPoint.AbstractF2m pNeg, byte[] u)
669679
{
670680
ECCurve curve = p.getCurve();
671681
ECPoint.AbstractF2m q = (ECPoint.AbstractF2m)curve.getInfinity();
672-
ECPoint.AbstractF2m pNeg = (ECPoint.AbstractF2m)p.negate();
673682
int tauCount = 0;
674683
for (int i = u.length - 1; i >= 0; i--)
675684
{
@@ -724,49 +733,71 @@ public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda, int width, int tw,
724733
byte[] u = new byte[maxLength];
725734

726735
int pow2Width = 1 << width;
727-
728-
// 2^(width - 1)
729-
int pow2wMin1 = pow2Width >>> 1;
736+
int pow2Mask = pow2Width - 1;
737+
int s = 32 - width;
730738

731739
// Split lambda into two BigIntegers to simplify calculations
732-
BigInteger r0 = lambda.u;
733-
BigInteger r1 = lambda.v;
734-
int i = 0;
740+
BigInteger R0 = lambda.u;
741+
BigInteger R1 = lambda.v;
742+
int uPos = 0;
735743

736744
// while lambda <> (0, 0)
737-
while ((r0.signum() | r1.signum()) != 0)
745+
while (R0.bitLength() > 62 || R1.bitLength() > 62)
738746
{
739-
if (r0.testBit(0))
747+
if (R0.testBit(0))
740748
{
741-
int uUnMod = (r0.intValue() + (r1.intValue() * tw)) & (pow2Width - 1);
749+
int uVal = R0.intValue() + (R1.intValue() * tw);
750+
int alphaPos = uVal & pow2Mask;
742751

743-
if (uUnMod >= pow2wMin1)
744-
{
745-
u[i] = (byte)(uUnMod - pow2Width);
746-
r0 = r0.add(alpha[pow2Width - uUnMod].u);
747-
r1 = r1.add(alpha[pow2Width - uUnMod].v);
748-
}
749-
else
750-
{
751-
u[i] = (byte)uUnMod;
752-
r0 = r0.subtract(alpha[uUnMod].u);
753-
r1 = r1.subtract(alpha[uUnMod].v);
754-
}
752+
u[uPos] = (byte)((uVal << s) >> s);
753+
R0 = R0.subtract(alpha[alphaPos].u);
754+
R1 = R1.subtract(alpha[alphaPos].v);
755755
}
756756

757-
++i;
757+
++uPos;
758758

759-
BigInteger t = r0.shiftRight(1);
759+
BigInteger t = R0.shiftRight(1);
760760
if (mu == 1)
761761
{
762-
r0 = r1.add(t);
762+
R0 = R1.add(t);
763763
}
764764
else // mu == -1
765765
{
766-
r0 = r1.subtract(t);
766+
R0 = R1.subtract(t);
767767
}
768-
r1 = t.negate();
768+
R1 = t.negate();
769769
}
770+
771+
long r0_64 = BigIntegers.longValueExact(R0);
772+
long r1_64 = BigIntegers.longValueExact(R1);
773+
774+
// while lambda <> (0, 0)
775+
while ((r0_64 | r1_64) != 0L)
776+
{
777+
if ((r0_64 & 1L) != 0L)
778+
{
779+
int uVal = (int)r0_64 + ((int)r1_64 * tw);
780+
int alphaPos = uVal & pow2Mask;
781+
782+
u[uPos] = (byte)((uVal << s) >> s);
783+
r0_64 -= alpha[alphaPos].u.intValue();
784+
r1_64 -= alpha[alphaPos].v.intValue();
785+
}
786+
787+
++uPos;
788+
789+
long t_64 = r0_64 >> 1;
790+
if (mu == 1)
791+
{
792+
r0_64 = r1_64 + t_64;
793+
}
794+
else // mu == -1
795+
{
796+
r0_64 = r1_64 - t_64;
797+
}
798+
r1_64 = -t_64;
799+
}
800+
770801
return u;
771802
}
772803

@@ -778,6 +809,7 @@ public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda, int width, int tw,
778809
*/
779810
public static ECPoint.AbstractF2m[] getPreComp(ECPoint.AbstractF2m p, byte a)
780811
{
812+
ECPoint.AbstractF2m pNeg = (ECPoint.AbstractF2m)p.negate();
781813
byte[][] alphaTnaf = (a == 0) ? Tnaf.alpha0Tnaf : Tnaf.alpha1Tnaf;
782814

783815
ECPoint.AbstractF2m[] pu = new ECPoint.AbstractF2m[(alphaTnaf.length + 1) >>> 1];
@@ -786,7 +818,7 @@ public static ECPoint.AbstractF2m[] getPreComp(ECPoint.AbstractF2m p, byte a)
786818
int precompLen = alphaTnaf.length;
787819
for (int i = 3; i < precompLen; i += 2)
788820
{
789-
pu[i >>> 1] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]);
821+
pu[i >>> 1] = Tnaf.multiplyFromTnaf(p, pNeg, alphaTnaf[i]);
790822
}
791823

792824
p.getCurve().normalizeAll(pu);

0 commit comments

Comments
 (0)