Arg aliasing in elliptic curves (#150)

* Jacobian addition can handle aliasing fine

* handle aliasing and use less mem for Jacobian double

* Handle aliasing for Projective EC
This commit is contained in:
Mamy Ratsimbazafy 2021-02-06 19:32:44 +01:00 committed by GitHub
parent 5710a961a1
commit 94419db783
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 100 additions and 99 deletions

View File

@ -56,7 +56,7 @@ func `==`*(P, Q: ECP_ShortW_Jac): SecretBool =
b *= z1z1
result = result and a == b
func isInf*(P: ECP_ShortW_Jac): SecretBool =
func isInf*(P: ECP_ShortW_Jac): SecretBool {.inline.} =
## Returns true if P is an infinity point
## and false otherwise
##
@ -66,13 +66,13 @@ func isInf*(P: ECP_ShortW_Jac): SecretBool =
## Y can be anything
result = P.z.isZero()
func setInf*(P: var ECP_ShortW_Jac) =
func setInf*(P: var ECP_ShortW_Jac) {.inline.} =
## Set ``P`` to infinity
P.x.setOne()
P.y.setOne()
P.z.setZero()
func ccopy*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac, ctl: SecretBool) =
func ccopy*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac, ctl: SecretBool) {.inline.} =
## Constant-time conditional copy
## If ctl is true: Q is copied into P
## if ctl is false: Q is not copied and P is unmodified
@ -119,17 +119,17 @@ func trySetFromCoordX*[F; Tw](
P.x = x
P.z.setOne()
func neg*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac) =
func neg*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac) {.inline.} =
## Negate ``P``
P.x = Q.x
P.y.neg(Q.y)
P.z = Q.z
func neg*(P: var ECP_ShortW_Jac) =
func neg*(P: var ECP_ShortW_Jac) {.inline.} =
## Negate ``P``
P.y.neg()
func cneg*(P: var ECP_ShortW_Jac, ctl: CTBool) =
func cneg*(P: var ECP_ShortW_Jac, ctl: CTBool) {.inline.} =
## Conditional negation.
## Negate if ``ctl`` is true
P.y.cneg(ctl)
@ -267,6 +267,7 @@ func sum*[F; Tw: static Twisted](
# - HHH_or_Mpre contains HHH (add) or garbage precomputation (dbl)
# - V_or_S is set with V = U₁*HH (add) or S = X₁*YY (dbl)
block: # Finishing line
# we can start using r, while carefully handling r and P or Q aliasing
var t {.noInit.}: F
t.double(V_or_S)
r.x.square(R_or_M)
@ -403,50 +404,50 @@ func double*[F; Tw: static Twisted](
# Y₃ = E*(D-X₃)-8*C
# Z₃ = 2*Y₁*Z₁
#
var A {.noInit.}, B{.noInit.}, C {.noInit.}, D{.noInit.}: F
var A {.noInit.}, B{.noInit.}, C {.noInit.}: F
A.square(P.x)
B.square(P.y)
C.square(B)
D.sum(P.x, B)
D.square()
D -= A
D -= C
D *= 2 # D = 2*((X₁+B)²-A-C)
B += P.x
# aliasing: we don't use P.x anymore
B.square()
B -= A
B -= C
B.double() # D = 2*((X₁+B)²-A-C)
A *= 3 # E = 3*A
r.x.square(A) # F = E²
B.double(D)
r.x -= B
r.x -= B # X₃ = F-2*D
B.diff(D, r.x) # (D-X₃)
r.y.prod(A, B) # E*(D-X₃)
B -= r.x # (D-X₃)
A *= B # E*(D-X₃)
C *= 8
r.y -= C # Y₃ = E*(D-X₃)-8*C
r.z.prod(P.y, P.z)
r.z *= 2 # Z₃ = 2*Y₁*Z₁
r.z.prod(P.z, P.y)
r.z.double() # Z₃ = 2*Y₁*Z₁
# aliasing: we don't use P.y, P.z anymore
r.y.diff(A, C) # Y₃ = E*(D-X₃)-8*C
else:
{.error: "Not implemented.".}
func `+=`*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac) =
func `+=`*(P: var ECP_ShortW_Jac, Q: ECP_ShortW_Jac) {.inline.} =
## In-place point addition
# TODO test for aliasing support
var tmp {.noInit.}: ECP_ShortW_Jac
tmp.sum(P, Q)
P = tmp
P.sum(P, Q)
func double*(P: var ECP_ShortW_Jac) =
var tmp {.noInit.}: ECP_ShortW_Jac
tmp.double(P)
P = tmp
func double*(P: var ECP_ShortW_Jac) {.inline.} =
## In-place point doubling
P.double(P)
func diff*(r: var ECP_ShortW_Jac,
P, Q: ECP_ShortW_Jac
) =
) {.inline.} =
## r = P - Q
## Can handle r and Q aliasing
var nQ = Q
nQ.neg()
var nQ {.noInit.}: typeof(Q)
nQ.neg(Q)
r.sum(P, nQ)
func affineFromJacobian*[F; Tw](

View File

@ -50,7 +50,7 @@ func `==`*(P, Q: ECP_ShortW_Prj): SecretBool =
b.prod(Q.y, P.z)
result = result and a == b
func isInf*(P: ECP_ShortW_Prj): SecretBool =
func isInf*(P: ECP_ShortW_Prj): SecretBool {.inline.} =
## Returns true if P is an infinity point
## and false otherwise
##
@ -60,13 +60,13 @@ func isInf*(P: ECP_ShortW_Prj): SecretBool =
## Y can be anything
result = P.x.isZero() and P.z.isZero()
func setInf*(P: var ECP_ShortW_Prj) =
func setInf*(P: var ECP_ShortW_Prj) {.inline.} =
## Set ``P`` to infinity
P.x.setZero()
P.y.setOne()
P.z.setZero()
func ccopy*(P: var ECP_ShortW_Prj, Q: ECP_ShortW_Prj, ctl: SecretBool) =
func ccopy*(P: var ECP_ShortW_Prj, Q: ECP_ShortW_Prj, ctl: SecretBool) {.inline.} =
## Constant-time conditional copy
## If ctl is true: Q is copied into P
## if ctl is false: Q is not copied and P is unmodified
@ -110,17 +110,17 @@ func trySetFromCoordX*[F; Tw](
P.x = x
P.z.setOne()
func neg*(P: var ECP_ShortW_Prj, Q: ECP_ShortW_Prj) =
func neg*(P: var ECP_ShortW_Prj, Q: ECP_ShortW_Prj) {.inline.} =
## Negate ``P``
P.x = Q.x
P.y.neg(Q.y)
P.z = Q.z
func neg*(P: var ECP_ShortW_Prj) =
func neg*(P: var ECP_ShortW_Prj) {.inline.} =
## Negate ``P``
P.y.neg()
func cneg*(P: var ECP_ShortW_Prj, ctl: CTBool) =
func cneg*(P: var ECP_ShortW_Prj, ctl: CTBool) {.inline.} =
## Conditional negation.
## Negate if ``ctl`` is true
P.y.cneg(ctl)
@ -167,6 +167,7 @@ func sum*[F; Tw: static Twisted](
when F.C.getCoefA() == 0:
var t0 {.noInit.}, t1 {.noInit.}, t2 {.noInit.}, t3 {.noInit.}, t4 {.noInit.}: F
var x3 {.noInit.}, y3 {.noInit.}, z3 {.noInit.}: F
const b3 = 3 * F.C.getCoefB()
# Algorithm 7 for curves: y² = x³ + b
@ -188,39 +189,39 @@ func sum*[F; Tw: static Twisted](
when Tw == OnTwist and F.C.getSexticTwist() == D_Twist:
t3 *= SexticNonResidue
t4.sum(P.y, P.z) # 9. t₄ <- Y₁ + Z₁
r.x.sum(Q.y, Q.z) # 10. X₃ <- Y₂ + Z₂
t4 *= r.x # 11. t₄ <- t₄ X₃
r.x.sum(t1, t2) # 12. X₃ <- t₁ + t₂ X₃ = Y₁Y₂ + Z₁Z₂
t4 -= r.x # 13. t₄ <- t₄ - X₃ t₄ = (Y₁ + Z₁)(Y₂ + Z₂) - (Y₁Y₂ + Z₁Z₂) = Y₁Z₂ + Y₂Z₁
x3.sum(Q.y, Q.z) # 10. X₃ <- Y₂ + Z₂
t4 *= x3 # 11. t₄ <- t₄ X₃
x3.sum(t1, t2) # 12. X₃ <- t₁ + t₂ X₃ = Y₁Y₂ + Z₁Z₂
t4 -= x3 # 13. t₄ <- t₄ - X₃ t₄ = (Y₁ + Z₁)(Y₂ + Z₂) - (Y₁Y₂ + Z₁Z₂) = Y₁Z₂ + Y₂Z₁
when Tw == OnTwist and F.C.getSexticTwist() == D_Twist:
t4 *= SexticNonResidue
r.x.sum(P.x, P.z) # 14. X₃ <- X₁ + Z₁
r.y.sum(Q.x, Q.z) # 15. Y₃ <- X₂ + Z₂
r.x *= r.y # 16. X₃ <- X₃ Y₃ X₃ = (X₁Z₁)(X₂Z₂)
r.y.sum(t0, t2) # 17. Y₃ <- t₀ + t₂ Y₃ = X₁ X₂ + Z₁ Z₂
r.y.diff(r.x, r.y) # 18. Y₃ <- X₃ - Y₃ Y₃ = (X₁ + Z₁)(X₂ + Z₂) - (X₁ X₂ + Z₁ Z₂) = X₁Z₂ + X₂Z₁
x3.sum(P.x, P.z) # 14. X₃ <- X₁ + Z₁
y3.sum(Q.x, Q.z) # 15. Y₃ <- X₂ + Z₂
x3 *= y3 # 16. X₃ <- X₃ Y₃ X₃ = (X₁Z₁)(X₂Z₂)
y3.sum(t0, t2) # 17. Y₃ <- t₀ + t₂ Y₃ = X₁ X₂ + Z₁ Z₂
y3.diff(x3, y3) # 18. Y₃ <- X₃ - Y₃ Y₃ = (X₁ + Z₁)(X₂ + Z₂) - (X₁ X₂ + Z₁ Z₂) = X₁Z₂ + X₂Z₁
when Tw == OnTwist and F.C.getSexticTwist() == D_Twist:
t0 *= SexticNonResidue
t1 *= SexticNonResidue
r.x.double(t0) # 19. X₃ <- t₀ + t₀ X₃ = 2 X₁X₂
t0 += r.x # 20. t₀ <- X₃ + t₀ t₀ = 3 X₁X₂
x3.double(t0) # 19. X₃ <- t₀ + t₀ X₃ = 2 X₁X₂
t0 += x3 # 20. t₀ <- X₃ + t₀ t₀ = 3 X₁X₂
t2 *= b3 # 21. t₂ <- 3b t₂ t₂ = 3bZ₁Z₂
when Tw == OnTwist and F.C.getSexticTwist() == M_Twist:
t2 *= SexticNonResidue
r.z.sum(t1, t2) # 22. Z₃ <- t₁ + t₂ Z₃ = Y₁Y₂ + 3bZ₁Z₂
z3.sum(t1, t2) # 22. Z₃ <- t₁ + t₂ Z₃ = Y₁Y₂ + 3bZ₁Z₂
t1 -= t2 # 23. t₁ <- t₁ - t₂ t₁ = Y₁Y₂ - 3bZ₁Z₂
r.y *= b3 # 24. Y₃ <- 3b Y₃ Y₃ = 3b(X₁Z₂ + X₂Z₁)
y3 *= b3 # 24. Y₃ <- 3b Y₃ Y₃ = 3b(X₁Z₂ + X₂Z₁)
when Tw == OnTwist and F.C.getSexticTwist() == M_Twist:
r.y *= SexticNonResidue
r.x.prod(t4, r.y) # 25. X₃ <- t₄ Y₃ X₃ = 3b(Y₁Z₂ + Y₂Z₁)(X₁Z₂ + X₂Z₁)
y3 *= SexticNonResidue
x3.prod(t4, y3) # 25. X₃ <- t₄ Y₃ X₃ = 3b(Y₁Z₂ + Y₂Z₁)(X₁Z₂ + X₂Z₁)
t2.prod(t3, t1) # 26. t₂ <- t₃ t₁ t₂ = (X₁Y₂ + X₂Y₁) (Y₁Y₂ - 3bZ₁Z₂)
r.x.diff(t2, r.x) # 27. X₃ <- t₂ - X₃ X₃ = (X₁Y₂ + X₂Y₁) (Y₁Y₂ - 3bZ₁Z₂) - 3b(Y₁Z₂ + Y₂Z₁)(X₁Z₂ + X₂Z₁)
r.y *= t0 # 28. Y₃ <- Y₃ t₀ Y₃ = 9bX₁X₂ (X₁Z₂ + X₂Z₁)
t1 *= r.z # 29. t₁ <- t₁ Z₃ t₁ = (Y₁Y₂ - 3bZ₁Z₂)(Y₁Y₂ + 3bZ₁Z₂)
r.y += t1 # 30. Y₃ <- t₁ + Y₃ Y₃ = (Y₁Y₂ + 3bZ₁Z₂)(Y₁Y₂ - 3bZ₁Z₂) + 9bX₁X₂ (X₁Z₂ + X₂Z₁)
r.x.diff(t2, x3) # 27. X₃ <- t₂ - X₃ X₃ = (X₁Y₂ + X₂Y₁) (Y₁Y₂ - 3bZ₁Z₂) - 3b(Y₁Z₂ + Y₂Z₁)(X₁Z₂ + X₂Z₁)
y3 *= t0 # 28. Y₃ <- Y₃ t₀ Y₃ = 9bX₁X₂ (X₁Z₂ + X₂Z₁)
t1 *= z3 # 29. t₁ <- t₁ Z₃ t₁ = (Y₁Y₂ - 3bZ₁Z₂)(Y₁Y₂ + 3bZ₁Z₂)
r.y.sum(y3, t1) # 30. Y₃ <- t₁ + Y₃ Y₃ = (Y₁Y₂ + 3bZ₁Z₂)(Y₁Y₂ - 3bZ₁Z₂) + 9bX₁X₂ (X₁Z₂ + X₂Z₁)
t0 *= t3 # 31. t₀ <- t₀ t₃ t₀ = 3X₁X₂ (X₁Y₂ + X₂Y₁)
r.z *= t4 # 32. Z₃ <- Z₃ t₄ Z₃ = (Y₁Y₂ + 3bZ₁Z₂)(Y₁Z₂ + Y₂Z₁)
r.z += t0 # 33. Z₃ <- Z₃ + t₀ Z₃ = (Y₁Z₂ + Y₂Z₁)(Y₁Y₂ + 3bZ₁Z₂) + 3X₁X₂ (X₁Y₂ + X₂Y₁)
z3 *= t4 # 32. Z₃ <- Z₃ t₄ Z₃ = (Y₁Y₂ + 3bZ₁Z₂)(Y₁Z₂ + Y₂Z₁)
r.z.sum(z3, t0) # 33. Z₃ <- Z₃ + t₀ Z₃ = (Y₁Z₂ + Y₂Z₁)(Y₁Y₂ + 3bZ₁Z₂) + 3X₁X₂ (X₁Y₂ + X₂Y₁)
else:
{.error: "Not implemented.".}
@ -238,6 +239,7 @@ func madd*[F; Tw: static Twisted](
when F.C.getCoefA() == 0:
var t0 {.noInit.}, t1 {.noInit.}, t2 {.noInit.}, t3 {.noInit.}, t4 {.noInit.}: F
var x3 {.noInit.}, y3 {.noInit.}, z3 {.noInit.}: F
const b3 = 3 * F.C.getCoefB()
# Algorithm 8 for curves: y² = x³ + b
@ -259,31 +261,31 @@ func madd*[F; Tw: static Twisted](
t4 += P.y # 9. t₄ <- t₄ + Y₁, t₄ = Y₁+Y₂Z₁
when Tw == OnTwist and F.C.getSexticTwist() == D_Twist:
t4 *= SexticNonResidue
r.y.prod(Q.x, P.z) # 10. Y₃ <- X₂ Z₁
r.y += P.x # 11. Y₃ <- Y₃ + X₁, Y₃ = X₁ + X₂Z₁
y3.prod(Q.x, P.z) # 10. Y₃ <- X₂ Z₁
y3 += P.x # 11. Y₃ <- Y₃ + X₁, Y₃ = X₁ + X₂Z₁
when Tw == OnTwist and F.C.getSexticTwist() == D_Twist:
t0 *= SexticNonResidue
t1 *= SexticNonResidue
r.x.double(t0) # 12. X₃ <- t₀ + t₀
t0 += r.x # 13. t₀ <- X₃ + t₀, t₀ = 3X₁X₂
x3.double(t0) # 12. X₃ <- t₀ + t₀
t0 += x3 # 13. t₀ <- X₃ + t₀, t₀ = 3X₁X₂
t2 = P.z
t2 *= b3 # 14. t₂ <- 3bZ₁
when Tw == OnTwist and F.C.getSexticTwist() == M_Twist:
t2 *= SexticNonResidue
r.z.sum(t1, t2) # 15. Z₃ <- t₁ + t₂, Z₃ = Y₁Y₂ + 3bZ₁
z3.sum(t1, t2) # 15. Z₃ <- t₁ + t₂, Z₃ = Y₁Y₂ + 3bZ₁
t1 -= t2 # 16. t₁ <- t₁ - t₂, t₁ = Y₁Y₂ - 3bZ₁
r.y *= b3 # 17. Y₃ <- 3bY₃, Y₃ = 3b(X₁ + X₂Z₁)
y3 *= b3 # 17. Y₃ <- 3bY₃, Y₃ = 3b(X₁ + X₂Z₁)
when Tw == OnTwist and F.C.getSexticTwist() == M_Twist:
r.y *= SexticNonResidue
r.x.prod(t4, r.y) # 18. X₃ <- t₄ Y₃, X₃ = (Y₁ + Y₂Z₁) 3b(X₁ + X₂Z₁)
y3 *= SexticNonResidue
x3.prod(t4, y3) # 18. X₃ <- t₄ Y₃, X₃ = (Y₁ + Y₂Z₁) 3b(X₁ + X₂Z₁)
t2.prod(t3, t1) # 19. t₂ <- t₃ t₁, t₂ = (X₁Y₂ + X₂Y₁)(Y₁Y₂ - 3bZ₁)
r.x.diff(t2, r.x) # 20. X₃ <- t₂ - X₃, X₃ = (X₁Y₂ + X₂Y₁)(Y₁Y₂ - 3bZ₁) - 3b(Y₁ + Y₂Z₁)(X₁ + X₂Z₁)
r.y *= t0 # 21. Y₃ <- Y₃ t₀, Y₃ = 9bX₁X₂ (X₁ + X₂Z₁)
t1 *= r.z # 22. t₁ <- t₁ Z₃, t₁ = (Y₁Y₂ - 3bZ₁)(Y₁Y₂ + 3bZ₁)
r.y += t1 # 23. Y₃ <- t₁ + Y₃, Y₃ = (Y₁Y₂ + 3bZ₁)(Y₁Y₂ - 3bZ₁) + 9bX₁X₂ (X₁ + X₂Z₁)
r.x.diff(t2, x3) # 20. X₃ <- t₂ - X₃, X₃ = (X₁Y₂ + X₂Y₁)(Y₁Y₂ - 3bZ₁) - 3b(Y₁ + Y₂Z₁)(X₁ + X₂Z₁)
y3 *= t0 # 21. Y₃ <- Y₃ t₀, Y₃ = 9bX₁X₂ (X₁ + X₂Z₁)
t1 *= z3 # 22. t₁ <- t₁ Z₃, t₁ = (Y₁Y₂ - 3bZ₁)(Y₁Y₂ + 3bZ₁)
r.y.sum(y3, t1) # 23. Y₃ <- t₁ + Y₃, Y₃ = (Y₁Y₂ + 3bZ₁)(Y₁Y₂ - 3bZ₁) + 9bX₁X₂ (X₁ + X₂Z₁)
t0 *= t3 # 31. t₀ <- t₀ t₃, t₀ = 3X₁X₂ (X₁Y₂ + X₂Y₁)
r.z *= t4 # 32. Z₃ <- Z₃ t₄, Z₃ = (Y₁Y₂ + 3bZ₁)(Y₁ + Y₂Z₁)
r.z += t0 # 33. Z₃ <- Z₃ + t₀, Z₃ = (Y₁ + Y₂Z₁)(Y₁Y₂ + 3bZ₁) + 3X₁X₂ (X₁Y₂ + X₂Y₁)
z3 *= t4 # 32. Z₃ <- Z₃ t₄, Z₃ = (Y₁Y₂ + 3bZ₁)(Y₁ + Y₂Z₁)
r.z.sum(z3, t0) # 33. Z₃ <- Z₃ + t₀, Z₃ = (Y₁ + Y₂Z₁)(Y₁Y₂ + 3bZ₁) + 3X₁X₂ (X₁Y₂ + X₂Y₁)
else:
{.error: "Not implemented.".}
@ -323,7 +325,8 @@ func double*[F; Tw: static Twisted](
# Cost: 8M + 3S + 3 mul(a) + 2 mul(3b) + 15a
when F.C.getCoefA() == 0:
var t0 {.noInit.}, t1 {.noInit.}, t2 {.noInit.}, snrY {.noInit.}: F
var t0 {.noInit.}, t1 {.noInit.}, t2 {.noInit.}: F
var x3 {.noInit.}, y3 {.noInit.}, z3 {.noInit.}: F
const b3 = 3 * F.C.getCoefB()
# Algorithm 9 for curves:
@ -332,59 +335,56 @@ func double*[F; Tw: static Twisted](
# X₃ = 2XY(Y² - 9bZ²)
# Y₃ = (Y² - 9bZ²)(Y² + 3bZ²) + 24bY²Z²
# Z₃ = 8Y³Z
snrY = P.y
when Tw == OnTwist and F.C.getSexticTwist() == D_Twist:
snrY *= SexticNonResidue
var snrY {.noInit.}: F
snrY.prod(P.y, SexticNonResidue)
t0.square(P.y)
t0 *= SexticNonResidue
else:
template snrY: untyped = P.y
t0.square(P.y) # 1. t₀ <- Y Y
r.z.double(t0) # 2. Z₃ <- t₀ + t₀
r.z.double() # 3. Z₃ <- Z₃ + Z₃
r.z.double() # 4. Z₃ <- Z₃ + Z₃ Z₃ = 8Y²
z3.double(t0) # 2. Z₃ <- t₀ + t₀
z3.double() # 3. Z₃ <- Z₃ + Z₃
z3.double() # 4. Z₃ <- Z₃ + Z₃ Z₃ = 8Y²
t1.prod(snrY, P.z) # 5. t₁ <- Y Z
t2.square(P.z) # 6. t₂ <- Z Z
t2 *= b3 # 7. t₂ <- 3b t₂
when Tw == OnTwist and F.C.getSexticTwist() == M_Twist:
t2 *= SexticNonResidue
r.x.prod(t2, r.z) # 8. X₃ <- t₂ Z₃
r.y.sum(t0, t2) # 9. Y₃ <- t₀ + t₂
r.z *= t1 # 10. Z₃ <- t₁ Z₃
x3.prod(t2, z3) # 8. X₃ <- t₂ Z₃
y3.sum(t0, t2) # 9. Y₃ <- t₀ + t₂
r.z.prod(z3, t1) # 10. Z₃ <- t₁ Z₃
t1.double(t2) # 11. t₁ <- t₂ + t₂
t2 += t1 # 12. t₂ <- t₁ + t₂
t0 -= t2 # 13. t₀ <- t₀ - t₂
r.y *= t0 # 14. Y₃ <- t₀ Y₃
r.y += r.x # 15. Y₃ <- X₃ + Y₃
t1.prod(P.x, snrY) # 16. t₁ <- X Y
r.x.prod(t0, t1) # 17. X₃ <- t₀ t₁
r.x.double() # 18. X₃ <- X₃ + X₃
y3 *= t0 # 14. Y₃ <- t₀ Y₃
t1.prod(P.x, snrY) # 16. t₁ <- X Y - snrY aliases P.y on Fp
r.y.sum(y3, x3) # 15. Y₃ <- X₃ + Y₃
x3.prod(t0, t1) # 17. X₃ <- t₀ t₁
r.x.double(x3) # 18. X₃ <- X₃ + X₃
else:
{.error: "Not implemented.".}
func `+=`*(P: var ECP_ShortW_Prj, Q: ECP_ShortW_Prj) =
func `+=`*(P: var ECP_ShortW_Prj, Q: ECP_ShortW_Prj) {.inline.} =
## In-place point addition
# TODO test for aliasing support
var tmp {.noInit.}: ECP_ShortW_Prj
tmp.sum(P, Q)
P = tmp
P.sum(P, Q)
func `+=`*(P: var ECP_ShortW_Prj, Q: ECP_ShortW_Aff) =
func `+=`*(P: var ECP_ShortW_Prj, Q: ECP_ShortW_Aff) {.inline.} =
## In-place mixed point addition
# used in line_addition
P.madd(P, Q)
func double*(P: var ECP_ShortW_Prj) =
var tmp {.noInit.}: ECP_ShortW_Prj
tmp.double(P)
P = tmp
func double*(P: var ECP_ShortW_Prj) {.inline.} =
## In-place EC doubling
P.double(P)
func diff*(r: var ECP_ShortW_Prj,
P, Q: ECP_ShortW_Prj
) =
) {.inline.} =
## r = P - Q
## Can handle r and Q aliasing
var nQ = Q
nQ.neg()
var nQ {.noInit.}: typeof(Q)
nQ.neg(Q)
r.sum(P, nQ)
func affineFromProjective*[F, Tw](