From 7a11eb6b398e7485692333e1da983ad6514b8387 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Fri, 21 Aug 2026 14:27:04 -0700 Subject: [PATCH] Eliminate redundant memory copy calls. --- src/assembly/fe.ts | 40 +++++++++++++++++++++++++++++++--------- src/assembly/ge.ts | 17 ++++++----------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/assembly/fe.ts b/src/assembly/fe.ts index e79f535..06abed1 100644 --- a/src/assembly/fe.ts +++ b/src/assembly/fe.ts @@ -92,8 +92,20 @@ export function fe_cmov (f: usize, g: usize, b: u64): void { /** * Copy values from one FieldElement to another. * - * @param h FieldElement destination - * @param f FieldElement source + * @param {usize} h pointer to FieldElement destination + * @param {usize} f pointer to FieldElement source + */ +//@ts-expect-error +@inline +export function fe_memcopy (h: usize, f: usize): void { + memory.copy(h, f, 40) +} + +/** + * Copy values from one FieldElement to another. + * + * @param {FieldElement} h destination + * @param {FieldElement} f source */ //@ts-expect-error @inline @@ -566,17 +578,27 @@ export function fe_mul (h: FieldElement, f: FieldElement, g: FieldElement): void /** * Negate the values of a FieldElement and store the result. * - * @param h FieldElement result destination - * @param f FieldElement operand source + * @param {usize} h pointer to FieldElement result destination + * @param {usize} f pointer to FieldElement operand source + */ +//@ts-expect-error +@inline +export function fe_memneg (h: usize, f: usize): void { + v128.store(h, v128.neg(v128.load(f))) + v128.store(h, v128.neg(v128.load(f, 16)), 16) + v128.store_lane(h, v128.neg(v128.load(f, 32)), 0, 32) +} + +/** + * Negate the values of a FieldElement and store the result. + * + * @param {FieldElement} h result destination + * @param {FieldElement} f operand source */ //@ts-expect-error @inline export function fe_neg (h: FieldElement, f: FieldElement): void { - const h_ptr = changetype(h) - const f_ptr = changetype(f) - v128.store(h_ptr, v128.neg(v128.load(f_ptr))) - v128.store(h_ptr, v128.neg(v128.load(f_ptr, 16)), 16) - v128.store_lane(h_ptr, v128.neg(v128.load(f_ptr, 32)), 0, 32) + fe_memneg(changetype(h), changetype(f)) } const fe_pow22523_t0: FieldElement = fe() diff --git a/src/assembly/ge.ts b/src/assembly/ge.ts index 1f48fcf..c514d34 100644 --- a/src/assembly/ge.ts +++ b/src/assembly/ge.ts @@ -19,7 +19,7 @@ import { base } from './base' import { base2 } from './base2' import { ed25519_d, fe_sqrtm1 } from './constants' -import { FieldElement, fe, fe_1, fe_add, fe_cmov, fe_copy, fe_frombytes, fe_isnegative, fe_iszero, fe_mul, fe_neg, fe_pow22523, fe_sq, fe_sub } from './fe' +import { FieldElement, fe, fe_1, fe_add, fe_cmov, fe_frombytes, fe_isnegative, fe_iszero, fe_memcopy, fe_memneg, fe_mul, fe_neg, fe_pow22523, fe_sq, fe_sub } from './fe' import { ge_add_cached, ge_add_precomp, ge_cached, ge_p1p1, ge_p1p1_to_p2, ge_p1p1_to_p3, ge_p2, ge_p2_0, ge_p2_dbl, ge_p2_to_p3, ge_p3, ge_p3_0, ge_p3_dbl, ge_p3_to_cached, ge_p3_tobytes, ge_precomp, ge_precomp_0, ge_sub_cached, ge_sub_precomp } from './p' import { equal, negative } from './utils' @@ -31,8 +31,7 @@ function ge_cmov (t: ge_precomp, u: usize, b: u8): void { fe_cmov(changetype(t.xy2d), u + 96, b) } -const p: ge_precomp = new ge_precomp() -const q: usize = changetype(new StaticArray(36)) +const p = changetype(new StaticArray(36)) //@ts-expect-error @inline function ge_cmov8_base (t: ge_precomp, offset: i32, b: i8): void { @@ -45,15 +44,11 @@ function ge_cmov8_base (t: ge_precomp, offset: i32, b: i8): void { ge_cmov(t, baseptr, equal(babs, i8(i + 1))) } - fe_copy(p.yplusx, t.yminusx) - fe_copy(p.yminusx, t.yplusx) - fe_neg(p.xy2d, t.xy2d) + fe_memcopy(p, changetype(t.yminusx)) + fe_memcopy(p + 48, changetype(t.yplusx)) + fe_memneg(p + 96, changetype(t.xy2d)) - memory.copy(q, changetype(p.yplusx), 48) - memory.copy(q + 48, changetype(p.yminusx), 48) - memory.copy(q + 96, changetype(p.xy2d), 48) - - ge_cmov(t, q, bnegative) + ge_cmov(t, p, bnegative) } const u: FieldElement = fe() -- 2.52.0