xref: /llvm-project/mlir/include/mlir/Dialect/Complex/IR/ComplexOps.td (revision 08a321e1b7ffdd72154ae808821d20fe511c83b6)
1//===- ComplexOps.td - Complex op definitions ----------------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef COMPLEX_OPS
10#define COMPLEX_OPS
11
12include "mlir/Dialect/Arith/IR/ArithBase.td"
13include "mlir/Dialect/Arith/IR/ArithOpsInterfaces.td"
14include "mlir/Dialect/Complex/IR/ComplexBase.td"
15include "mlir/IR/OpAsmInterface.td"
16include "mlir/Interfaces/InferTypeOpInterface.td"
17include "mlir/Interfaces/SideEffectInterfaces.td"
18
19class Complex_Op<string mnemonic, list<Trait> traits = []>
20    : Op<Complex_Dialect, mnemonic, traits>;
21
22// Base class for standard arithmetic operations on complex numbers with a
23// floating-point element type. These operations take two operands and return
24// one result, all of which must be complex numbers of the same type.
25class ComplexArithmeticOp<string mnemonic, list<Trait> traits = []> :
26    Complex_Op<mnemonic, traits # [Pure, SameOperandsAndResultType,
27    Elementwise, DeclareOpInterfaceMethods<ArithFastMathInterface>]> {
28  let arguments = (ins Complex<AnyFloat>:$lhs, Complex<AnyFloat>:$rhs, DefaultValuedAttr<
29        Arith_FastMathAttr, "::mlir::arith::FastMathFlags::none">:$fastmath);
30  let results = (outs Complex<AnyFloat>:$result);
31  let assemblyFormat = "$lhs `,` $rhs (`fastmath` `` $fastmath^)? attr-dict `:` type($result)";
32}
33
34// Base class for standard unary operations on complex numbers with a
35// floating-point element type. These operations take one operand and return
36// one result; the operand must be a complex number.
37class ComplexUnaryOp<string mnemonic, list<Trait> traits = []> :
38    Complex_Op<mnemonic, traits # [Pure, Elementwise, DeclareOpInterfaceMethods<ArithFastMathInterface>]> {
39  let arguments = (ins Complex<AnyFloat>:$complex, DefaultValuedAttr<
40        Arith_FastMathAttr, "::mlir::arith::FastMathFlags::none">:$fastmath);
41  let assemblyFormat = "$complex (`fastmath` `` $fastmath^)? attr-dict `:` type($complex)";
42}
43
44//===----------------------------------------------------------------------===//
45// AbsOp
46//===----------------------------------------------------------------------===//
47
48def AbsOp : ComplexUnaryOp<"abs",
49    [TypesMatchWith<"complex element type matches result type",
50                    "complex", "result",
51                    "::llvm::cast<ComplexType>($_self).getElementType()">]> {
52  let summary = "computes absolute value of a complex number";
53  let description = [{
54    The `abs` op takes a single complex number and computes its absolute value.
55
56    Example:
57
58    ```mlir
59    %a = complex.abs %b : complex<f32>
60    ```
61  }];
62  let results = (outs AnyFloat:$result);
63}
64
65//===----------------------------------------------------------------------===//
66// AddOp
67//===----------------------------------------------------------------------===//
68
69def AddOp : ComplexArithmeticOp<"add"> {
70  let summary = "complex addition";
71  let description = [{
72    The `add` operation takes two complex numbers and returns their sum.
73
74    Example:
75
76    ```mlir
77    %a = complex.add %b, %c : complex<f32>
78    ```
79  }];
80
81  let hasFolder = 1;
82}
83
84//===----------------------------------------------------------------------===//
85// Atan2
86//===----------------------------------------------------------------------===//
87
88def Atan2Op : ComplexArithmeticOp<"atan2"> {
89  let summary = "complex 2-argument arctangent";
90  let description = [{
91    For complex numbers it is expressed using complex logarithm
92    atan2(y, x) = -i * log((x + i * y) / sqrt(x**2 + y**2))
93
94    Example:
95
96    ```mlir
97    %a = complex.atan2 %b, %c : complex<f32>
98    ```
99  }];
100}
101
102
103//===----------------------------------------------------------------------===//
104// Bitcast
105//===----------------------------------------------------------------------===//
106
107def BitcastOp : Complex_Op<"bitcast", [Pure]> {
108
109  let summary = "computes bitcast between complex and equal arith types";
110  let description = [{
111
112    Example:
113
114    ```mlir
115         %a = complex.bitcast %b : complex<f32> -> i64
116    ```
117  }];
118  let assemblyFormat = "$operand attr-dict `:` type($operand) `to` type($result)";
119  let arguments = (ins AnyType:$operand);
120  let results = (outs AnyType:$result);
121
122  let hasCanonicalizer = 1;
123  let hasFolder = 1;
124  let hasVerifier = 1;
125}
126
127//===----------------------------------------------------------------------===//
128// ConstantOp
129//===----------------------------------------------------------------------===//
130
131def ConstantOp : Complex_Op<"constant", [
132    ConstantLike, Pure,
133    DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>
134  ]> {
135  let summary = "complex number constant operation";
136  let description = [{
137    The `complex.constant` operation creates a constant complex number from an
138    attribute containing the real and imaginary parts.
139
140    Example:
141
142    ```mlir
143    %a = complex.constant [0.1, -1.0] : complex<f64>
144    ```
145  }];
146
147  let arguments = (ins ArrayAttr:$value);
148  let results = (outs AnyComplex:$complex);
149
150  let assemblyFormat = "$value attr-dict `:` type($complex)";
151  let hasFolder = 1;
152  let hasVerifier = 1;
153
154  let extraClassDeclaration = [{
155    /// Returns true if a constant operation can be built with the given value
156    /// and result type.
157    static bool isBuildableWith(Attribute value, Type type);
158  }];
159}
160
161//===----------------------------------------------------------------------===//
162// CosOp
163//===----------------------------------------------------------------------===//
164
165def CosOp : ComplexUnaryOp<"cos", [SameOperandsAndResultType]> {
166  let summary = "computes cosine of a complex number";
167  let description = [{
168    The `cos` op takes a single complex number and computes the cosine of
169    it, i.e. `cos(x)`, where `x` is the input value.
170
171    Example:
172
173    ```mlir
174    %a = complex.cos %b : complex<f32>
175    ```
176  }];
177
178  let results = (outs Complex<AnyFloat>:$result);
179}
180
181//===----------------------------------------------------------------------===//
182// CreateOp
183//===----------------------------------------------------------------------===//
184
185def CreateOp : Complex_Op<"create",
186    [Pure,
187     AllTypesMatch<["real", "imaginary"]>,
188     TypesMatchWith<"complex element type matches real operand type",
189                    "complex", "real",
190                    "::llvm::cast<ComplexType>($_self).getElementType()">,
191     TypesMatchWith<"complex element type matches imaginary operand type",
192                    "complex", "imaginary",
193                    "::llvm::cast<ComplexType>($_self).getElementType()">]> {
194
195  let summary = "complex number creation operation";
196  let description = [{
197    The `complex.create` operation creates a complex number from two
198    floating-point operands, the real and the imaginary part.
199
200    Example:
201
202    ```mlir
203    %a = complex.create %b, %c : complex<f32>
204    ```
205  }];
206
207  let arguments = (ins AnyFloat:$real, AnyFloat:$imaginary);
208  let results = (outs Complex<AnyFloat>:$complex);
209
210  let assemblyFormat = "$real `,` $imaginary attr-dict `:` type($complex)";
211  let hasFolder = 1;
212}
213
214//===----------------------------------------------------------------------===//
215// DivOp
216//===----------------------------------------------------------------------===//
217
218def DivOp : ComplexArithmeticOp<"div"> {
219  let summary = "complex division";
220  let description = [{
221    The `div` operation takes two complex numbers and returns result of their
222    division:
223
224    ```mlir
225    %a = complex.div %b, %c : complex<f32>
226    ```
227  }];
228
229  let hasFolder = 1;
230}
231
232//===----------------------------------------------------------------------===//
233// EqualOp
234//===----------------------------------------------------------------------===//
235
236def EqualOp : Complex_Op<"eq",
237    [Pure, AllTypesMatch<["lhs", "rhs"]>, Elementwise]> {
238  let summary = "computes whether two complex values are equal";
239  let description = [{
240    The `eq` op takes two complex numbers and returns whether they are equal.
241
242    Example:
243
244    ```mlir
245    %a = complex.eq %b, %c : complex<f32>
246    ```
247  }];
248
249  let arguments = (ins Complex<AnyFloat>:$lhs, Complex<AnyFloat>:$rhs);
250  let results = (outs I1:$result);
251
252  let assemblyFormat = "$lhs `,` $rhs  attr-dict `:` type($lhs)";
253}
254
255//===----------------------------------------------------------------------===//
256// ExpOp
257//===----------------------------------------------------------------------===//
258
259def ExpOp : ComplexUnaryOp<"exp", [SameOperandsAndResultType]> {
260  let summary = "computes exponential of a complex number";
261  let description = [{
262    The `exp` op takes a single complex number and computes the exponential of
263    it, i.e. `exp(x)` or `e^(x)`, where `x` is the input value.
264    `e` denotes Euler's number and is approximately equal to 2.718281.
265
266    Example:
267
268    ```mlir
269    %a = complex.exp %b : complex<f32>
270    ```
271  }];
272
273  let results = (outs Complex<AnyFloat>:$result);
274
275  let hasFolder = 1;
276}
277
278//===----------------------------------------------------------------------===//
279// Expm1Op
280//===----------------------------------------------------------------------===//
281
282def Expm1Op : ComplexUnaryOp<"expm1", [SameOperandsAndResultType]> {
283  let summary = "computes exponential of a complex number minus 1";
284  let description = [{
285    complex.expm1(x) := complex.exp(x) - 1
286
287    Example:
288
289    ```mlir
290    %a = complex.expm1 %b : complex<f32>
291    ```
292  }];
293
294  let results = (outs Complex<AnyFloat>:$result);
295}
296
297//===----------------------------------------------------------------------===//
298// ImOp
299//===----------------------------------------------------------------------===//
300
301def ImOp : ComplexUnaryOp<"im",
302    [TypesMatchWith<"complex element type matches result type",
303                    "complex", "imaginary",
304                    "::llvm::cast<ComplexType>($_self).getElementType()">]> {
305  let summary = "extracts the imaginary part of a complex number";
306  let description = [{
307    The `im` op takes a single complex number and extracts the imaginary part.
308
309    Example:
310
311    ```mlir
312    %a = complex.im %b : complex<f32>
313    ```
314  }];
315
316  let results = (outs AnyFloat:$imaginary);
317  let hasFolder = 1;
318  let hasCanonicalizer = 1;
319}
320
321//===----------------------------------------------------------------------===//
322// LogOp
323//===----------------------------------------------------------------------===//
324
325def LogOp : ComplexUnaryOp<"log", [SameOperandsAndResultType]> {
326  let summary = "computes natural logarithm of a complex number";
327  let description = [{
328    The `log` op takes a single complex number and computes the natural
329    logarithm of it, i.e. `log(x)` or `log_e(x)`, where `x` is the input value.
330    `e` denotes Euler's number and is approximately equal to 2.718281.
331
332    Example:
333
334    ```mlir
335    %a = complex.log %b : complex<f32>
336    ```
337  }];
338
339  let results = (outs Complex<AnyFloat>:$result);
340
341  let hasFolder = 1;
342}
343
344//===----------------------------------------------------------------------===//
345// Log1pOp
346//===----------------------------------------------------------------------===//
347
348def Log1pOp : ComplexUnaryOp<"log1p", [SameOperandsAndResultType]> {
349  let summary = "computes natural logarithm of a complex number";
350  let description = [{
351    The `log` op takes a single complex number and computes the natural
352    logarithm of one plus the given value, i.e. `log(1 + x)` or `log_e(1 + x)`,
353    where `x` is the input value. `e` denotes Euler's number and is
354    approximately equal to 2.718281.
355
356    Example:
357
358    ```mlir
359    %a = complex.log1p %b : complex<f32>
360    ```
361  }];
362
363  let results = (outs Complex<AnyFloat>:$result);
364}
365
366//===----------------------------------------------------------------------===//
367// MulOp
368//===----------------------------------------------------------------------===//
369
370def MulOp : ComplexArithmeticOp<"mul"> {
371  let summary = "complex multiplication";
372  let description = [{
373    The `mul` operation takes two complex numbers and returns their product:
374
375    ```mlir
376    %a = complex.mul %b, %c : complex<f32>
377    ```
378  }];
379
380  let hasFolder = 1;
381}
382
383//===----------------------------------------------------------------------===//
384// NegOp
385//===----------------------------------------------------------------------===//
386
387def NegOp : ComplexUnaryOp<"neg", [SameOperandsAndResultType]> {
388  let summary = "Negation operator";
389  let description = [{
390    The `neg` op takes a single complex number `complex` and returns `-complex`.
391
392    Example:
393
394    ```mlir
395    %a = complex.neg %b : complex<f32>
396    ```
397  }];
398
399  let results = (outs Complex<AnyFloat>:$result);
400
401  let hasFolder = 1;
402}
403
404//===----------------------------------------------------------------------===//
405// NotEqualOp
406//===----------------------------------------------------------------------===//
407
408def NotEqualOp : Complex_Op<"neq",
409    [Pure, AllTypesMatch<["lhs", "rhs"]>, Elementwise]> {
410  let summary = "computes whether two complex values are not equal";
411  let description = [{
412    The `neq` op takes two complex numbers and returns whether they are not
413    equal.
414
415    Example:
416
417    ```mlir
418    %a = complex.neq %b, %c : complex<f32>
419    ```
420  }];
421
422  let arguments = (ins Complex<AnyFloat>:$lhs, Complex<AnyFloat>:$rhs);
423  let results = (outs I1:$result);
424
425  let assemblyFormat = "$lhs `,` $rhs  attr-dict `:` type($lhs)";
426}
427
428//===----------------------------------------------------------------------===//
429// PowOp
430//===----------------------------------------------------------------------===//
431
432def PowOp : ComplexArithmeticOp<"pow"> {
433  let summary = "complex power function";
434  let description = [{
435    The `sqrt` operation takes a complex number raises it to the given complex
436    exponent.
437
438    Example:
439
440    ```mlir
441    %a = complex.pow %b, %c : complex<f32>
442    ```
443  }];
444}
445
446//===----------------------------------------------------------------------===//
447// ReOp
448//===----------------------------------------------------------------------===//
449
450def ReOp : ComplexUnaryOp<"re",
451    [TypesMatchWith<"complex element type matches result type",
452                    "complex", "real",
453                    "::llvm::cast<ComplexType>($_self).getElementType()">]> {
454  let summary = "extracts the real part of a complex number";
455  let description = [{
456    The `re` op takes a single complex number and extracts the real part.
457
458    Example:
459
460    ```mlir
461    %a = complex.re %b : complex<f32>
462    ```
463  }];
464
465  let results = (outs AnyFloat:$real);
466  let hasFolder = 1;
467  let hasCanonicalizer = 1;
468}
469
470//===----------------------------------------------------------------------===//
471// RsqrtOp
472//===----------------------------------------------------------------------===//
473
474def RsqrtOp : ComplexUnaryOp<"rsqrt", [SameOperandsAndResultType]> {
475  let summary = "complex reciprocal of square root";
476  let description = [{
477    The `rsqrt` operation computes reciprocal of square root.
478
479    Example:
480
481    ```mlir
482    %a = complex.rsqrt %b : complex<f32>
483    ```
484  }];
485
486  let results = (outs Complex<AnyFloat>:$result);
487}
488
489//===----------------------------------------------------------------------===//
490// SignOp
491//===----------------------------------------------------------------------===//
492
493def SignOp : ComplexUnaryOp<"sign", [SameOperandsAndResultType]> {
494  let summary = "computes sign of a complex number";
495  let description = [{
496    The `sign` op takes a single complex number and computes the sign of
497    it, i.e. `y = sign(x) = x / |x|` if `x != 0`, otherwise `y = 0`.
498
499    Example:
500
501    ```mlir
502    %a = complex.sign %b : complex<f32>
503    ```
504  }];
505
506  let results = (outs Complex<AnyFloat>:$result);
507}
508
509//===----------------------------------------------------------------------===//
510// SinOp
511//===----------------------------------------------------------------------===//
512
513def SinOp : ComplexUnaryOp<"sin", [SameOperandsAndResultType]> {
514  let summary = "computes sine of a complex number";
515  let description = [{
516    The `sin` op takes a single complex number and computes the sine of
517    it, i.e. `sin(x)`, where `x` is the input value.
518
519    Example:
520
521    ```mlir
522    %a = complex.sin %b : complex<f32>
523    ```
524  }];
525
526  let results = (outs Complex<AnyFloat>:$result);
527}
528
529//===----------------------------------------------------------------------===//
530// SqrtOp
531//===----------------------------------------------------------------------===//
532
533def SqrtOp : ComplexUnaryOp<"sqrt", [SameOperandsAndResultType]> {
534  let summary = "complex square root";
535  let description = [{
536    The `sqrt` operation takes a complex number and returns its square root.
537
538    Example:
539
540    ```mlir
541    %a = complex.sqrt %b : complex<f32>
542    ```
543  }];
544
545  let results = (outs Complex<AnyFloat>:$result);
546}
547
548//===----------------------------------------------------------------------===//
549// SubOp
550//===----------------------------------------------------------------------===//
551
552def SubOp : ComplexArithmeticOp<"sub"> {
553  let summary = "complex subtraction";
554  let description = [{
555    The `sub` operation takes two complex numbers and returns their difference.
556
557    Example:
558
559    ```mlir
560    %a = complex.sub %b, %c : complex<f32>
561    ```
562  }];
563
564  let hasFolder = 1;
565}
566
567//===----------------------------------------------------------------------===//
568// TanhOp
569//===----------------------------------------------------------------------===//
570
571def TanhOp : ComplexUnaryOp<"tanh", [SameOperandsAndResultType]> {
572  let summary = "complex hyperbolic tangent";
573  let description = [{
574    The `tanh` operation takes a complex number and returns its hyperbolic
575    tangent.
576
577    Example:
578
579    ```mlir
580    %a = complex.tanh %b : complex<f32>
581    ```
582  }];
583
584  let results = (outs Complex<AnyFloat>:$result);
585}
586
587//===----------------------------------------------------------------------===//
588// TanOp
589//===----------------------------------------------------------------------===//
590
591def TanOp : ComplexUnaryOp<"tan", [SameOperandsAndResultType]> {
592  let summary = "computes tangent of a complex number";
593  let description = [{
594    The `tan` op takes a single complex number and computes the tangent of
595    it, i.e. `tan(x)`, where `x` is the input value.
596
597    Example:
598
599    ```mlir
600    %a = complex.tan %b : complex<f32>
601    ```
602  }];
603  let results = (outs Complex<AnyFloat>:$result);
604}
605
606//===----------------------------------------------------------------------===//
607// Conj
608//===----------------------------------------------------------------------===//
609
610def ConjOp : ComplexUnaryOp<"conj", [SameOperandsAndResultType]> {
611  let summary = "Calculate the complex conjugate";
612  let description = [{
613    The `conj` op takes a single complex number and computes the
614    complex conjugate.
615
616    Example:
617
618    ```mlir
619    %a = complex.conj %b: complex<f32>
620    ```
621  }];
622
623  let results = (outs Complex<AnyFloat>:$result);
624  let hasFolder = 1;
625}
626
627//===----------------------------------------------------------------------===//
628// AngleOp
629//===----------------------------------------------------------------------===//
630
631def AngleOp : ComplexUnaryOp<"angle",
632                           [TypesMatchWith<"complex element type matches result type",
633                                           "complex", "result",
634                                           "::llvm::cast<ComplexType>($_self).getElementType()">]> {
635  let summary = "computes argument value of a complex number";
636  let description = [{
637    The `angle` op takes a single complex number and computes its argument value with a branch cut along the negative real axis.
638
639    Example:
640
641    ```mlir
642         %a = complex.angle %b : complex<f32>
643    ```
644  }];
645  let results = (outs AnyFloat:$result);
646}
647
648#endif // COMPLEX_OPS
649