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