Skip to content

Commit e503360

Browse files
committed
feat(elliptic_curve): add JacobianA0Double
Jacobian double when A=0
1 parent ac8f4f1 commit e503360

File tree

2 files changed

+77
-16
lines changed
  • zkir/Dialect/EllipticCurve/Conversions/EllipticCurveToField/PointOperations/Jacobian

2 files changed

+77
-16
lines changed

zkir/Dialect/EllipticCurve/Conversions/EllipticCurveToField/PointOperations/Jacobian/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ cc_library(
3232
"//zkir/Dialect/Field/IR:Field",
3333
"@llvm-project//mlir:ArithDialect",
3434
"@llvm-project//mlir:IR",
35+
"@llvm-project//mlir:SCFDialect",
3536
"@llvm-project//mlir:TensorDialect",
3637
],
3738
)

zkir/Dialect/EllipticCurve/Conversions/EllipticCurveToField/PointOperations/Jacobian/Double.cpp

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "zkir/Dialect/EllipticCurve/Conversions/EllipticCurveToField/PointOperations/Jacobian/Double.h"
22

33
#include "mlir/Dialect/Arith/IR/Arith.h"
4+
#include "mlir/Dialect/SCF/IR/SCF.h"
45
#include "mlir/Dialect/Tensor/IR/Tensor.h"
56
#include "mlir/IR/ImplicitLocOpBuilder.h"
67
#include "zkir/Dialect/EllipticCurve/IR/EllipticCurveTypes.h"
@@ -13,17 +14,14 @@ namespace mlir::zkir::elliptic_curve {
1314
// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-mdbl-2007-bl
1415
// Cost: 1M + 5S
1516
// Assumption: Z == 1
16-
Value affineToJacobianDouble(const Value &point, Type affineType,
17+
Value affineToJacobianDouble(const Value &point, const Value &a,
1718
ImplicitLocOpBuilder &b) {
1819
Value zero = b.create<arith::ConstantIndexOp>(0);
1920
Value one = b.create<arith::ConstantIndexOp>(1);
2021

2122
auto x = b.create<tensor::ExtractOp>(point, zero);
2223
auto y = b.create<tensor::ExtractOp>(point, one);
2324

24-
field::PrimeFieldType basefield = cast<field::PrimeFieldType>(x.getType());
25-
field::PrimeFieldAttr aAttr;
26-
2725
// XX = X²
2826
auto xx = b.create<field::SquareOp>(x);
2927
// YY = Y²
@@ -39,8 +37,6 @@ Value affineToJacobianDouble(const Value &point, Type affineType,
3937
// M = 3*XX+a
4038
auto mTmp1 = b.create<field::DoubleOp>(xx);
4139
auto mTmp2 = b.create<field::AddOp>(mTmp1, xx);
42-
aAttr = cast<AffineType>(affineType).getCurve().getA();
43-
auto a = b.create<field::ConstantOp>(basefield, aAttr.getValue());
4440
auto m = b.create<field::AddOp>(mTmp2, a);
4541
// X3 = M²-2*S
4642
auto x3Tmp1 = b.create<field::SquareOp>(m);
@@ -59,10 +55,56 @@ Value affineToJacobianDouble(const Value &point, Type affineType,
5955
return b.create<tensor::FromElementsOp>(SmallVector<Value>({x3, y3, z3}));
6056
}
6157

58+
// dbl-2009-l
59+
// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
60+
// Cost: 2M + 5S
61+
Value jacobianA0Double(const Value &point, ImplicitLocOpBuilder &b) {
62+
Value zero = b.create<arith::ConstantIndexOp>(0);
63+
Value one = b.create<arith::ConstantIndexOp>(1);
64+
Value two = b.create<arith::ConstantIndexOp>(2);
65+
66+
auto x = b.create<tensor::ExtractOp>(point, zero);
67+
auto y = b.create<tensor::ExtractOp>(point, one);
68+
auto z = b.create<tensor::ExtractOp>(point, two);
69+
70+
// A = X²
71+
auto a = b.create<field::SquareOp>(x);
72+
// B = Y²
73+
auto yy = b.create<field::SquareOp>(y);
74+
// C = B²
75+
auto c = b.create<field::SquareOp>(yy);
76+
// D = 2*((X+B)²-A-C)
77+
auto dTmp1 = b.create<field::AddOp>(x, yy);
78+
auto dTmp2 = b.create<field::SquareOp>(dTmp1);
79+
auto dTmp3 = b.create<field::SubOp>(dTmp2, a);
80+
auto dTmp4 = b.create<field::SubOp>(dTmp3, c);
81+
auto d = b.create<field::DoubleOp>(dTmp4);
82+
// E = 3*A
83+
auto eTmp1 = b.create<field::DoubleOp>(a);
84+
auto e = b.create<field::AddOp>(eTmp1, a);
85+
// F = E²
86+
auto f = b.create<field::SquareOp>(e);
87+
// X3 = F-2*D
88+
auto x3Tmp1 = b.create<field::DoubleOp>(d);
89+
auto x3 = b.create<field::SubOp>(f, x3Tmp1);
90+
// Y3 = E*(D-X3)-8*C
91+
auto y3Tmp1 = b.create<field::SubOp>(d, x3);
92+
auto y3Tmp2 = b.create<field::MulOp>(e, y3Tmp1);
93+
auto y3Tmp3 = b.create<field::DoubleOp>(c);
94+
auto y3Tmp4 = b.create<field::DoubleOp>(y3Tmp3);
95+
auto y3Tmp5 = b.create<field::DoubleOp>(y3Tmp4);
96+
auto y3 = b.create<field::SubOp>(y3Tmp2, y3Tmp5);
97+
// Z3 = 2*Y*Z
98+
auto z3Tmp1 = b.create<field::DoubleOp>(y);
99+
auto z3 = b.create<field::MulOp>(z3Tmp1, z);
100+
101+
return b.create<tensor::FromElementsOp>(SmallVector<Value>({x3, y3, z3}));
102+
}
103+
62104
// dbl-2007-bl
63105
// https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl
64106
// Cost: 1M + 8S + 1*a
65-
Value jacobianDefaultDouble(const Value &point, Type jacobianType,
107+
Value jacobianDefaultDouble(const Value &point, const Value &a,
66108
ImplicitLocOpBuilder &b) {
67109
Value zero = b.create<arith::ConstantIndexOp>(0);
68110
Value one = b.create<arith::ConstantIndexOp>(1);
@@ -72,9 +114,6 @@ Value jacobianDefaultDouble(const Value &point, Type jacobianType,
72114
auto y = b.create<tensor::ExtractOp>(point, one);
73115
auto z = b.create<tensor::ExtractOp>(point, two);
74116

75-
field::PrimeFieldType basefield = cast<field::PrimeFieldType>(x.getType());
76-
field::PrimeFieldAttr aAttr;
77-
78117
// XX = X²
79118
auto xx = b.create<field::SquareOp>(x);
80119
// YY = Y²
@@ -93,8 +132,6 @@ Value jacobianDefaultDouble(const Value &point, Type jacobianType,
93132
auto mTmp1 = b.create<field::DoubleOp>(xx);
94133
auto mTmp2 = b.create<field::AddOp>(mTmp1, xx);
95134
auto mTmp3 = b.create<field::SquareOp>(zz);
96-
aAttr = cast<JacobianType>(jacobianType).getCurve().getA();
97-
auto a = b.create<field::ConstantOp>(basefield, aAttr.getValue());
98135
auto mTmp4 = b.create<field::MulOp>(a, mTmp3);
99136
auto m = b.create<field::AddOp>(mTmp2, mTmp4);
100137
// X3 = M²-2*S
@@ -119,10 +156,33 @@ Value jacobianDefaultDouble(const Value &point, Type jacobianType,
119156

120157
Value jacobianDouble(const Value &point, Type inputType,
121158
ImplicitLocOpBuilder &b) {
122-
if (isa<AffineType>(inputType)) {
123-
return affineToJacobianDouble(point, inputType, b);
124-
} else if (isa<JacobianType>(inputType)) {
125-
return jacobianDefaultDouble(point, inputType, b);
159+
auto baseField = cast<field::PrimeFieldType>(
160+
cast<RankedTensorType>(point.getType()).getElementType());
161+
field::PrimeFieldAttr aAttr;
162+
163+
if (auto affineType = dyn_cast<AffineType>(inputType)) {
164+
aAttr = affineType.getCurve().getA();
165+
auto a = b.create<field::ConstantOp>(baseField, aAttr.getValue());
166+
return affineToJacobianDouble(point, a, b);
167+
} else if (auto jacobianType = dyn_cast<JacobianType>(inputType)) {
168+
aAttr = jacobianType.getCurve().getA();
169+
auto a = b.create<field::ConstantOp>(baseField, aAttr.getValue());
170+
auto zero = b.create<field::ConstantOp>(baseField, 0);
171+
172+
auto cmpEq = b.create<field::CmpOp>(arith::CmpIPredicate::eq, a, zero);
173+
auto ifOp = b.create<scf::IfOp>(
174+
cmpEq,
175+
/*thenBuilder=*/
176+
[&](OpBuilder &builder, Location loc) {
177+
ImplicitLocOpBuilder b(loc, builder);
178+
b.create<scf::YieldOp>(jacobianA0Double(point, b));
179+
},
180+
/*elseBuilder=*/
181+
[&](OpBuilder &builder, Location loc) {
182+
ImplicitLocOpBuilder b(loc, builder);
183+
b.create<scf::YieldOp>(jacobianDefaultDouble(point, a, b));
184+
});
185+
return ifOp.getResult(0);
126186
} else {
127187
assert(false && "Unsupported point type for Jacobian doubling");
128188
}

0 commit comments

Comments
 (0)