]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/internal/fips140/edwards25519/field: speed up Element.Bytes
authorAlexander Yastrebov <yastrebov.alex@gmail.com>
Fri, 7 Feb 2025 11:29:34 +0000 (11:29 +0000)
committerGopher Robot <gobot@golang.org>
Fri, 7 Feb 2025 16:39:38 +0000 (08:39 -0800)
Write bytes in 64-bit chunks made from adjacent limbs.

goos: linux
goarch: amd64
pkg: crypto/internal/fips140/edwards25519/field
cpu: Intel(R) Core(TM) i5-8350U CPU @ 1.70GHz
        │   HEAD~1    │                HEAD                 │
        │   sec/op    │   sec/op     vs base                │
Bytes-8   76.14n ± 3%   13.61n ± 3%  -82.13% (p=0.000 n=10)

        │   HEAD~1   │              HEAD              │
        │    B/op    │    B/op     vs base            │
Bytes-8   0.000 ± 0%   0.000 ± 0%  ~ (p=1.000 n=10) ¹
¹ all samples are equal

        │   HEAD~1   │              HEAD              │
        │ allocs/op  │ allocs/op   vs base            │
Bytes-8   0.000 ± 0%   0.000 ± 0%  ~ (p=1.000 n=10) ¹
¹ all samples are equal

Change-Id: Iaecc32da7fd8df96ff048e1e855a990f44dc9db5
GitHub-Last-Rev: d0e1583a4faf8cc3471af03437107cc0e5770d57
GitHub-Pull-Request: golang/go#71603
Reviewed-on: https://go-review.googlesource.com/c/go/+/647595
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>

src/crypto/internal/fips140/edwards25519/field/fe.go
src/crypto/internal/fips140/edwards25519/field/fe_bench_test.go

index 2d76ba72740b800f614702151590624e3b406fce..21bedefa0ca7d378d5ee5289128d61c154097db6 100644 (file)
@@ -233,18 +233,22 @@ func (v *Element) bytes(out *[32]byte) []byte {
        t := *v
        t.reduce()
 
-       var buf [8]byte
-       for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} {
-               bitsOffset := i * 51
-               byteorder.LEPutUint64(buf[:], l<<uint(bitsOffset%8))
-               for i, bb := range buf {
-                       off := bitsOffset/8 + i
-                       if off >= len(out) {
-                               break
-                       }
-                       out[off] |= bb
-               }
-       }
+       // Pack five 51-bit limbs into four 64-bit words:
+       //
+       //  255    204    153    102     51      0
+       //    ├──l4──┼──l3──┼──l2──┼──l1──┼──l0──┤
+       //   ├───u3───┼───u2───┼───u1───┼───u0───┤
+       // 256      192      128       64        0
+
+       u0 := t.l1<<51 | t.l0
+       u1 := t.l2<<(102-64) | t.l1>>(64-51)
+       u2 := t.l3<<(153-128) | t.l2>>(128-102)
+       u3 := t.l4<<(204-192) | t.l3>>(192-153)
+
+       byteorder.LEPutUint64(out[0*8:], u0)
+       byteorder.LEPutUint64(out[1*8:], u1)
+       byteorder.LEPutUint64(out[2*8:], u2)
+       byteorder.LEPutUint64(out[3*8:], u3)
 
        return out[:]
 }
index 84fdf05a8e474a78294cdd767ddf8ddd31bf687b..fb80ca88fe255dff2a7b1a330e29fa01ff3779b2 100644 (file)
@@ -47,3 +47,11 @@ func BenchmarkMult32(b *testing.B) {
                x.Mult32(x, 0xaa42aa42)
        }
 }
+
+func BenchmarkBytes(b *testing.B) {
+       x := new(Element).One()
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               x.Bytes()
+       }
+}