ARM NEON实现中的Karatsuba算法似乎有错误

ARM NEON实现中的Karatsuba算法似乎有错误,arm,multiplication,neon,karatsuba,Arm,Multiplication,Neon,Karatsuba,我在互联网上找到了许多相同的ARM NEON Karatsuba算法实现的副本,包括一些科学论文,例如 看起来所有这些副本都有相同的问题。虽然说它做算术乘法,但结果仍然是多项式。如果将vmull.p8更改为vmull.u8,它将为最小一个字的小数字生成正确的结果。但超过最低单词的大数字是不正确的。 实施看起来不错: .macro mul64_p8 rq rl rh ad bd k16 k32 k48 t0q t0l t0h t1q t1l t1h t2q t2l t2h t3q t3l t3h

我在互联网上找到了许多相同的ARM NEON Karatsuba算法实现的副本,包括一些科学论文,例如

看起来所有这些副本都有相同的问题。虽然说它做算术乘法,但结果仍然是多项式。如果将
vmull.p8
更改为
vmull.u8
,它将为最小一个字的小数字生成正确的结果。但超过最低单词的大数字是不正确的。 实施看起来不错:

.macro mul64_p8 rq rl rh ad bd k16 k32 k48 t0q t0l t0h t1q t1l t1h t2q t2l t2h t3q t3l t3h
    @A1
    vext.8  \t0l, \ad, \ad, $1
    @F = A1*B
    vmull.p8 \t0q, \t0l, \bd
    @B1
    vext.8  \rl, \bd, \bd, $1
    @E = A*B1 (7)
    vmull.p8 \rq, \ad, \rl
        @A2
        vext.8  \t1l, \ad, \ad, $2
        @H = A2*B
        vmull.p8 \t1q, \t1l, \bd
        @B2
        vext.8  \t3l, \bd, \bd, $2
        @G = A*B2
        vmull.p8 \t3q, \ad, \t3l
            @A3
            vext.8  \t2l, \ad, \ad, $3
            @J = A3*B
            vmull.p8 \t2q, \t2l, \bd
    @L = E + F
    veor    \t0q, \t0q, \rq
            @B3
            vext.8  \rl, \bd, \bd, $3
            @I = A*B3
            vmull.p8 \rq, \ad, \rl
        @M = G + H
        veor    \t1q, \t1q, \t3q
                @B4
                vext.8  \t3l, \bd, \bd, $4
                @K = A*B4
                vmull.p8 \t3q, \ad, \t3l
    @t0 = (L) (P0 + P1) << 8
    veor    \t0l, \t0l, \t0h
    vand    \t0h, \t0h, \k48
        @t1 = (M) (P2 + P3) << 16
        veor    \t1l, \t1l, \t1h
        vand    \t1h, \t1h, \k32
            @N = I + J
            veor    \t2q, \t2q, \rq
    veor    \t0l, \t0l, \t0h
        veor    \t1l, \t1l, \t1h
            @t2 = (N) (P4 + P5) << 24
            veor    \t2l, \t2l, \t2h
            vand    \t2h, \t2h, \k16
                @t3 = (K) (P6 + P7) << 32
                veor    \t3l, \t3l, \t3h
                vmov.i64 \t3h, $0
    vext.8  \t0q, \t0q, \t0q, $15
            veor    \t2l, \t2l, \t2h
        vext.8  \t1q, \t1q, \t1q, $14
                vmull.p8 \rq, \ad, \bd
            vext.8  \t2q, \t2q, \t2q, $13
                vext.8  \t3q, \t3q, \t3q, $12
    veor    \t0q, \t0q, \t1q
    veor    \t2q, \t2q, \t3q
    veor    \rq, \rq, \t0q
    veor    \rq, \rq, \t2q
.endm
.macro mul64_p8 rq rl右侧ad bd k16 k32 k48 t0q t0l t0h t1q t1l t1h t2q t2l t2h t3q t3l t3h
@A1
vext.8\t0l\ad\ad$1
@F=A1*B
vmull.p8\t0q\t0l\bd
@B1
vext.8\rl\bd\bd$1
@E=A*B1(7)
vmull.p8\rq\ad\rl
@A2
vext.8\t1l\ad\ad$2
@H=A2*B
vmull.p8\t1q\t1l\bd
@B2
vext.8\t3l\bd\bd$2
@G=A*B2
vmull.p8\t3q\ad\t3l
@A3
vext.8\t2l\ad\ad$3
@J=A3*B
vmull.p8\t2q\t2l\bd
@L=E+F
veor\t0q\t0q\rq
@B3
vext.8\rl\bd\bd$3
@I=A*B3
vmull.p8\rq\ad\rl
@M=G+H
veor\t1q\t1q\t3q
@B4
vext.8\t3l\bd\bd$4
@K=A*B4
vmull.p8\t3q\ad\t3l

@t0=(L)(P0+P1)我“不”知道所展示的代码正在尝试做什么(可能成功)。它看起来当然不是64x64=128。从
VMULL.U32
开始,只需执行“长乘法”:在操作数如此小(支持的因子长度的两倍)的情况下,单靠进位处理将消除需要较少乘法的任何优势。(甚至(在AArch64模式下)UMULH,否则UMULL。)这是我想使用fast
64x64=128
还是我想知道/学习/练习如何实现fast
64x64=128
?对于前者,一个有自尊心的编译器应该能够指导您。(
carry handling本身会扼杀任何优势。
或者?)我“不”知道所展示的代码正在尝试做什么(可能成功)。它看起来当然不是64x64=128。从
VMULL.U32
开始,只需执行“长乘法”:在操作数如此小(支持的因子长度的两倍)的情况下,单靠进位处理将消除需要较少乘法的任何优势。(甚至(在AArch64模式下)UMULH,否则UMULL。)这是我想使用fast
64x64=128
还是我想知道/学习/练习如何实现fast
64x64=128
?对于前者,一个有自尊心的编译器应该能够指导您。(
carry-handling单独使用将扼杀任何优势
or?)