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