@@ -35,18 +35,18 @@ def Polynomial_Dialect : Dialect {
35
35
36
36
```mlir
37
37
// A constant polynomial in a ring with i32 coefficients and no polynomial modulus
38
- #ring = #polynomial.ring<ctype =i32>
38
+ #ring = #polynomial.ring<coefficientType =i32>
39
39
%a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring>
40
40
41
41
// A constant polynomial in a ring with i32 coefficients, modulo (x^1024 + 1)
42
42
#modulus = #polynomial.polynomial<1 + x**1024>
43
- #ring = #polynomial.ring<ctype =i32, ideal =#modulus>
43
+ #ring = #polynomial.ring<coefficientType =i32, polynomialModulus =#modulus>
44
44
%a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring>
45
45
46
46
// A constant polynomial in a ring with i32 coefficients, with a polynomial
47
47
// modulus of (x^1024 + 1) and a coefficient modulus of 17.
48
48
#modulus = #polynomial.polynomial<1 + x**1024>
49
- #ring = #polynomial.ring<ctype =i32, cmod =17, ideal =#modulus>
49
+ #ring = #polynomial.ring<coefficientType =i32, coefficientModulus =17, polynomialModulus =#modulus>
50
50
%a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring>
51
51
```
52
52
}];
@@ -63,7 +63,21 @@ class Polynomial_Attr<string name, string attrMnemonic, list<Trait> traits = []>
63
63
def Polynomial_PolynomialAttr : Polynomial_Attr<"Polynomial", "polynomial"> {
64
64
let summary = "An attribute containing a single-variable polynomial.";
65
65
let description = [{
66
- #poly = #polynomial.poly<x**1024 + 1>
66
+ A polynomial attribute represents a single-variable polynomial, which
67
+ is used to define the modulus of a `RingAttr`, as well as to define constants
68
+ and perform constant folding for `polynomial` ops.
69
+
70
+ The polynomial must be expressed as a list of monomial terms, with addition
71
+ or subtraction between them. The choice of variable name is arbitrary, but
72
+ must be consistent across all the monomials used to define a single
73
+ attribute. The order of monomial terms is arbitrary, each monomial degree
74
+ must occur at most once.
75
+
76
+ Example:
77
+
78
+ ```mlir
79
+ #poly = #polynomial.polynomial<x**1024 + 1>
80
+ ```
67
81
}];
68
82
let parameters = (ins "Polynomial":$polynomial);
69
83
let hasCustomAssemblyFormat = 1;
@@ -79,10 +93,10 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
79
93
integral, whose coefficients are taken modulo some statically known modulus
80
94
(`coefficientModulus`).
81
95
82
- Additionally, a polynomial ring can specify an _ideal_ , which converts
96
+ Additionally, a polynomial ring can specify a _polynomialModulus_ , which converts
83
97
polynomial arithmetic to the analogue of modular integer arithmetic, where
84
98
each polynomial is represented as its remainder when dividing by the
85
- modulus. For single-variable polynomials, an "ideal " is always specificed
99
+ modulus. For single-variable polynomials, an "polynomialModulus " is always specificed
86
100
via a single polynomial, which we call `polynomialModulus`.
87
101
88
102
An expressive example is polynomials with i32 coefficients, whose
@@ -122,32 +136,284 @@ class Polynomial_Type<string name, string typeMnemonic>
122
136
123
137
def Polynomial_PolynomialType : Polynomial_Type<"Polynomial", "polynomial"> {
124
138
let summary = "An element of a polynomial ring.";
125
-
126
139
let description = [{
127
140
A type for polynomials in a polynomial quotient ring.
128
141
}];
129
-
130
142
let parameters = (ins Polynomial_RingAttr:$ring);
131
143
let assemblyFormat = "`<` $ring `>`";
132
144
}
133
145
146
+ def PolynomialLike: TypeOrContainer<Polynomial_PolynomialType, "polynomial-like">;
147
+
134
148
class Polynomial_Op<string mnemonic, list<Trait> traits = []> :
135
- Op<Polynomial_Dialect, mnemonic, traits # [Pure]>;
149
+ Op<Polynomial_Dialect, mnemonic, traits # [Pure]> {
150
+ let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
151
+ }
136
152
137
153
class Polynomial_UnaryOp<string mnemonic, list<Trait> traits = []> :
138
154
Polynomial_Op<mnemonic, traits # [SameOperandsAndResultType]> {
139
155
let arguments = (ins Polynomial_PolynomialType:$operand);
140
156
let results = (outs Polynomial_PolynomialType:$result);
141
-
142
- let assemblyFormat = "$operand attr-dict `:` qualified(type($result))";
143
157
}
144
158
145
159
class Polynomial_BinaryOp<string mnemonic, list<Trait> traits = []> :
146
- Polynomial_Op<mnemonic, traits # [SameOperandsAndResultType]> {
147
- let arguments = (ins Polynomial_PolynomialType:$lhs, Polynomial_PolynomialType:$rhs);
148
- let results = (outs Polynomial_PolynomialType:$result);
160
+ Polynomial_Op<mnemonic, !listconcat(traits, [Pure, SameOperandsAndResultType, ElementwiseMappable])> {
161
+ let arguments = (ins PolynomialLike:$lhs, PolynomialLike:$rhs);
162
+ let results = (outs PolynomialLike:$result);
163
+ let assemblyFormat = "operands attr-dict `:` type($result)";
164
+ }
165
+
166
+ def Polynomial_AddOp : Polynomial_BinaryOp<"add", [Commutative]> {
167
+ let summary = "Addition operation between polynomials.";
168
+ let description = [{
169
+ Performs polynomial addition on the operands. The operands may be single
170
+ polynomials or containers of identically-typed polynomials, i.e., polynomials
171
+ from the same underlying ring with the same coefficient types.
172
+
173
+ Addition is defined to occur in the ring defined by the ring attribute of
174
+ the two operands, meaning the addition is taken modulo the coefficientModulus
175
+ and the polynomialModulus of the ring.
176
+
177
+ Example:
178
+
179
+ ```mlir
180
+ // add two polynomials modulo x^1024 - 1
181
+ #poly = #polynomial.polynomial<x**1024 - 1>
182
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
183
+ %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring>
184
+ %1 = polynomial.constant #polynomial.polynomial<x**5 - x + 1> : !polynomial.polynomial<#ring>
185
+ %2 = polynomial.add %0, %1 : !polynomial.polynomial<#ring>
186
+ ```
187
+ }];
188
+ }
189
+
190
+ def Polynomial_SubOp : Polynomial_BinaryOp<"sub"> {
191
+ let summary = "Subtraction operation between polynomials.";
192
+ let description = [{
193
+ Performs polynomial subtraction on the operands. The operands may be single
194
+ polynomials or containers of identically-typed polynomials, i.e., polynomials
195
+ from the same underlying ring with the same coefficient types.
196
+
197
+ Subtraction is defined to occur in the ring defined by the ring attribute of
198
+ the two operands, meaning the subtraction is taken modulo the coefficientModulus
199
+ and the polynomialModulus of the ring.
200
+
201
+ Example:
149
202
150
- let assemblyFormat = "$lhs `,` $rhs attr-dict `:` qualified(type($result))";
203
+ ```mlir
204
+ // subtract two polynomials modulo x^1024 - 1
205
+ #poly = #polynomial.polynomial<x**1024 - 1>
206
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
207
+ %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring>
208
+ %1 = polynomial.constant #polynomial.polynomial<x**5 - x + 1> : !polynomial.polynomial<#ring>
209
+ %2 = polynomial.sub %0, %1 : !polynomial.polynomial<#ring>
210
+ ```
211
+ }];
212
+ }
213
+
214
+ def Polynomial_MulOp : Polynomial_BinaryOp<"mul", [Commutative]> {
215
+ let summary = "Multiplication operation between polynomials.";
216
+ let description = [{
217
+ Performs polynomial multiplication on the operands. The operands may be single
218
+ polynomials or containers of identically-typed polynomials, i.e., polynomials
219
+ from the same underlying ring with the same coefficient types.
220
+
221
+ Multiplication is defined to occur in the ring defined by the ring attribute of
222
+ the two operands, meaning the multiplication is taken modulo the coefficientModulus
223
+ and the polynomialModulus of the ring.
224
+
225
+ Example:
226
+
227
+ ```mlir
228
+ // multiply two polynomials modulo x^1024 - 1
229
+ #poly = #polynomial.polynomial<x**1024 - 1>
230
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
231
+ %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring>
232
+ %1 = polynomial.constant #polynomial.polynomial<x**5 - x + 1> : !polynomial.polynomial<#ring>
233
+ %2 = polynomial.mul %0, %1 : !polynomial.polynomial<#ring>
234
+ ```
235
+ }];
236
+ }
237
+
238
+ def Polynomial_MulScalarOp : Polynomial_Op<"mul_scalar", [
239
+ ElementwiseMappable, AllTypesMatch<["polynomial", "output"]>]> {
240
+ let summary = "Multiplication by a scalar of the field.";
241
+ let description = [{
242
+ Multiplies the polynomial operand's coefficients by a given scalar value.
243
+ The operation is defined to occur in the ring defined by the ring attribute
244
+ of the two operands, meaning the multiplication is taken modulo the
245
+ coefficientModulus of the ring.
246
+
247
+ The `scalar` input must have the same type as the polynomial ring's
248
+ coefficientType.
249
+
250
+ Example:
251
+
252
+ ```mlir
253
+ // multiply two polynomials modulo x^1024 - 1
254
+ #poly = #polynomial.polynomial<x**1024 - 1>
255
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
256
+ %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring>
257
+ %1 = arith.constant 3 : i32
258
+ %2 = polynomial.mul_scalar %0, %1 : !polynomial.polynomial<#ring>, i32
259
+ ```
260
+ }];
261
+
262
+ let arguments = (ins
263
+ PolynomialLike:$polynomial,
264
+ AnyInteger:$scalar
265
+ );
266
+ let results = (outs
267
+ PolynomialLike:$output
268
+ );
269
+ let assemblyFormat = "operands attr-dict `:` type($polynomial) `,` type($scalar)";
270
+ let hasVerifier = 1;
271
+ }
272
+
273
+ def Polynomial_LeadingTermOp: Polynomial_Op<"leading_term"> {
274
+ let summary = "Compute the leading term of the polynomial.";
275
+ let description = [{
276
+ The degree of a polynomial is the largest $k$ for which the coefficient
277
+ `a_k` of `x^k` is nonzero. The leading term is the term `a_k * x^k`, which
278
+ this op represents as a pair of results. The first is the degree `k` as an
279
+ index, and the second is the coefficient, whose type matches the
280
+ coefficient type of the polynomial's ring attribute.
281
+
282
+ Example:
283
+
284
+ ```mlir
285
+ #poly = #polynomial.polynomial<x**1024 - 1>
286
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
287
+ %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring>
288
+ %1, %2 = polynomial.leading_term %0 : !polynomial.polynomial<#ring> -> (index, i32)
289
+ ```
290
+ }];
291
+ let arguments = (ins Polynomial_PolynomialType:$input);
292
+ let results = (outs Index:$degree, AnyInteger:$coefficient);
293
+ let assemblyFormat = "operands attr-dict `:` type($input) `->` `(` type($degree) `,` type($coefficient) `)`";
294
+ }
295
+
296
+ def Polynomial_MonomialOp: Polynomial_Op<"monomial"> {
297
+ let summary = "Create a polynomial that consists of a single monomial.";
298
+ let description = [{
299
+ Construct a polynomial that consists of a single monomial term, from its
300
+ degree and coefficient as dynamic inputs.
301
+
302
+ The coefficient type of the output polynomial's ring attribute must match
303
+ the `coefficient` input type.
304
+
305
+ Example:
306
+
307
+ ```mlir
308
+ #poly = #polynomial.polynomial<x**1024 - 1>
309
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
310
+ %deg = arith.constant 1023 : index
311
+ %five = arith.constant 5 : i32
312
+ %0 = polynomial.monomial %five, %deg : (i32, index) -> !polynomial.polynomial<#ring>
313
+ ```
314
+ }];
315
+ let arguments = (ins AnyInteger:$coefficient, Index:$degree);
316
+ let results = (outs Polynomial_PolynomialType:$output);
317
+ }
318
+
319
+ def Polynomial_MonicMonomialMulOp: Polynomial_Op<"monic_monomial_mul", [AllTypesMatch<["input", "output"]>]> {
320
+ let summary = "Multiply a polynomial by a monic monomial.";
321
+ let description = [{
322
+ Multiply a polynomial by a monic monomial, meaning a polynomial of the form
323
+ `1 * x^k` for an index operand `k`.
324
+
325
+ In some special rings of polynomials, such as a ring of polynomials
326
+ modulo `x^n - 1`, `monomial_mul` can be interpreted as a cyclic shift of
327
+ the coefficients of the polynomial. For some rings, this results in
328
+ optimized lowerings that involve rotations and rescaling of the
329
+ coefficients of the input.
330
+ }];
331
+ let arguments = (ins PolynomialLike:$input, Index:$monomialDegree);
332
+ let results = (outs PolynomialLike:$output);
333
+ }
334
+
335
+ def Polynomial_FromTensorOp : Polynomial_Op<"from_tensor", [Pure]> {
336
+ let summary = "Creates a polynomial from integer coefficients stored in a tensor.";
337
+ let description = [{
338
+ `polynomial.from_tensor` creates a polynomial value from a tensor of coefficients.
339
+ The input tensor must list the coefficients in degree-increasing order.
340
+
341
+ The input one-dimensional tensor may have size at most the degree of the
342
+ ring's polynomialModulus generator polynomial, with smaller dimension implying that
343
+ all higher-degree terms have coefficient zero.
344
+
345
+ Example:
346
+
347
+ ```mlir
348
+ #poly = #polynomial.polynomial<x**1024 - 1>
349
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
350
+ %two = arith.constant 2 : i32
351
+ %five = arith.constant 5 : i32
352
+ %coeffs = tensor.from_elements %two, %two, %five : tensor<3xi32>
353
+ %poly = polynomial.from_tensor %coeffs : tensor<3xi32> -> !polynomial.polynomial<#ring>
354
+ ```
355
+ }];
356
+ let arguments = (ins RankedTensorOf<[AnyInteger]>:$input);
357
+ let results = (outs Polynomial_PolynomialType:$output);
358
+
359
+ let assemblyFormat = "$input attr-dict `:` type($input) `->` type($output)";
360
+
361
+ let builders = [
362
+ // Builder that infers coefficient modulus from tensor bit width,
363
+ // and uses whatever input ring is provided by the caller.
364
+ OpBuilder<(ins "::mlir::Value":$input, "::mlir::polynomial::RingAttr":$ring)>
365
+ ];
366
+ let hasVerifier = 1;
367
+ }
368
+
369
+ def Polynomial_ToTensorOp : Polynomial_Op<"to_tensor", [Pure]> {
370
+ let summary = "Creates a tensor containing the coefficients of a polynomial.";
371
+ let description = [{
372
+ `polynomial.to_tensor` creates a dense tensor value containing the
373
+ coefficients of the input polynomial. The output tensor contains the
374
+ coefficients in degree-increasing order.
375
+
376
+ Operations that act on the coefficients of a polynomial, such as extracting
377
+ a specific coefficient or extracting a range of coefficients, should be
378
+ implemented by composing `to_tensor` with the relevant `tensor` dialect
379
+ ops.
380
+
381
+ The output tensor has shape equal to the degree of the polynomial ring
382
+ attribute's polynomialModulus, including zeroes.
383
+
384
+ Example:
385
+
386
+ ```mlir
387
+ #poly = #polynomial.polynomial<x**1024 - 1>
388
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
389
+ %two = arith.constant 2 : i32
390
+ %five = arith.constant 5 : i32
391
+ %coeffs = tensor.from_elements %two, %two, %five : tensor<3xi32>
392
+ %poly = polynomial.from_tensor %coeffs : tensor<3xi32> -> !polynomial.polynomial<#ring>
393
+ %tensor = polynomial.to_tensor %poly : !polynomial.polynomial<#ring> -> tensor<1024xi32>
394
+ ```
395
+ }];
396
+ let arguments = (ins Polynomial_PolynomialType:$input);
397
+ let results = (outs RankedTensorOf<[AnyInteger]>:$output);
398
+ let assemblyFormat = "$input attr-dict `:` type($input) `->` type($output)";
399
+
400
+ let hasVerifier = 1;
401
+ }
402
+
403
+ def Polynomial_ConstantOp : Polynomial_Op<"constant", [Pure]> {
404
+ let summary = "Define a constant polynomial via an attribute.";
405
+ let description = [{
406
+ Example:
407
+
408
+ ```mlir
409
+ #poly = #polynomial.polynomial<x**1024 - 1>
410
+ #ring = #polynomial.ring<coefficientType=i32, coefficientModulus=65536, polynomialModulus=#poly>
411
+ %0 = polynomial.constant #polynomial.polynomial<1 + x**2> : !polynomial.polynomial<#ring>
412
+ ```
413
+ }];
414
+ let arguments = (ins Polynomial_PolynomialAttr:$input);
415
+ let results = (outs Polynomial_PolynomialType:$output);
416
+ let assemblyFormat = "$input attr-dict `:` type($output)";
151
417
}
152
418
153
419
#endif // POLYNOMIAL_OPS
0 commit comments