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