//===- MathOps.cpp - MLIR operations for math implementation --------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/CommonFolders.h"
#include "mlir/Dialect/Math/IR/Math.h"
#include "mlir/Dialect/UB/IR/UBOps.h"
#include "mlir/IR/Builders.h"
#include <optional>

using namespace mlir;
using namespace mlir::math;

//===----------------------------------------------------------------------===//
// Common helpers
//===----------------------------------------------------------------------===//

/// Return the type of the same shape (scalar, vector or tensor) containing i1.
static Type getI1SameShape(Type type) {
  auto i1Type = IntegerType::get(type.getContext(), 1);
  if (auto shapedType = llvm::dyn_cast<ShapedType>(type))
    return shapedType.cloneWith(std::nullopt, i1Type);
  if (llvm::isa<UnrankedTensorType>(type))
    return UnrankedTensorType::get(i1Type);
  return i1Type;
}

//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//

#define GET_OP_CLASSES
#include "mlir/Dialect/Math/IR/MathOps.cpp.inc"

//===----------------------------------------------------------------------===//
// AbsFOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::AbsFOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOp<FloatAttr>(adaptor.getOperands(),
                                     [](const APFloat &a) { return abs(a); });
}

//===----------------------------------------------------------------------===//
// AbsIOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::AbsIOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOp<IntegerAttr>(adaptor.getOperands(),
                                       [](const APInt &a) { return a.abs(); });
}

//===----------------------------------------------------------------------===//
// AcosOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::AcosOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(acos(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(acosf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// AcoshOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::AcoshOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(acosh(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(acoshf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// AsinOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::AsinOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(asin(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(asinf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// AsinhOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::AsinhOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(asinh(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(asinhf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// AtanOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::AtanOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(atan(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(atanf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// AtanhOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::AtanhOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(atanh(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(atanhf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// Atan2Op folder
//===----------------------------------------------------------------------===//

OpFoldResult math::Atan2Op::fold(FoldAdaptor adaptor) {
  return constFoldBinaryOpConditional<FloatAttr>(
      adaptor.getOperands(),
      [](const APFloat &a, const APFloat &b) -> std::optional<APFloat> {
        if (a.isZero() && b.isZero())
          return llvm::APFloat::getNaN(a.getSemantics());

        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(atan2(a.convertToDouble(), b.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(atan2f(a.convertToFloat(), b.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// CbrtOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::CbrtOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(cbrt(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(cbrtf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// CeilOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::CeilOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOp<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) {
        APFloat result(a);
        result.roundToIntegral(llvm::RoundingMode::TowardPositive);
        return result;
      });
}

//===----------------------------------------------------------------------===//
// CopySignOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::CopySignOp::fold(FoldAdaptor adaptor) {
  return constFoldBinaryOp<FloatAttr>(adaptor.getOperands(),
                                      [](const APFloat &a, const APFloat &b) {
                                        APFloat result(a);
                                        result.copySign(b);
                                        return result;
                                      });
}

//===----------------------------------------------------------------------===//
// CosOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::CosOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(cos(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(cosf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// CoshOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::CoshOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(cosh(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(coshf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// SinOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::SinOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(sin(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(sinf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// SinhOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::SinhOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(sinh(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(sinhf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// SinCosOp
//===----------------------------------------------------------------------===//

std::optional<SmallVector<int64_t, 4>> math::SincosOp::getShapeForUnroll() {
  if (auto vt = mlir::dyn_cast<VectorType>(getOperand().getType()))
    return llvm::to_vector<4>(vt.getShape());
  return std::nullopt;
}

LogicalResult math::SincosOp::fold(FoldAdaptor adaptor,
                                   SmallVectorImpl<OpFoldResult> &result) {
  auto foldSincos = [](const APFloat &a, double (*fnDouble)(double),
                       float (*fnFloat)(float)) -> std::optional<APFloat> {
    switch (APFloat::SemanticsToEnum(a.getSemantics())) {
    case APFloat::Semantics::S_IEEEdouble:
      return APFloat(fnDouble(a.convertToDouble()));
    case APFloat::Semantics::S_IEEEsingle:
      return APFloat(fnFloat(a.convertToFloat()));
    default:
      return {};
    }
  };

  Attribute sinRes = constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(),
      [&](const APFloat &a) { return foldSincos(a, sin, sinf); });
  Attribute cosRes = constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(),
      [&](const APFloat &a) { return foldSincos(a, cos, cosf); });

  if (sinRes && cosRes) {
    result.push_back(sinRes);
    result.push_back(cosRes);
    return success();
  }
  return failure();
}

//===----------------------------------------------------------------------===//
// CountLeadingZerosOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::CountLeadingZerosOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOp<IntegerAttr>(
      adaptor.getOperands(),
      [](const APInt &a) { return APInt(a.getBitWidth(), a.countl_zero()); });
}

//===----------------------------------------------------------------------===//
// CountTrailingZerosOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::CountTrailingZerosOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOp<IntegerAttr>(
      adaptor.getOperands(),
      [](const APInt &a) { return APInt(a.getBitWidth(), a.countr_zero()); });
}

//===----------------------------------------------------------------------===//
// CtPopOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::CtPopOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOp<IntegerAttr>(
      adaptor.getOperands(),
      [](const APInt &a) { return APInt(a.getBitWidth(), a.popcount()); });
}

//===----------------------------------------------------------------------===//
// ErfOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::ErfOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(erf(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(erff(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// ErfcOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::ErfcOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(erfc(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(erfcf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// IPowIOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::IPowIOp::fold(FoldAdaptor adaptor) {
  return constFoldBinaryOpConditional<IntegerAttr>(
      adaptor.getOperands(),
      [](const APInt &base, const APInt &power) -> std::optional<APInt> {
        unsigned width = base.getBitWidth();
        auto zeroValue = APInt::getZero(width);
        // i1 folding is ambiguous with signed semantics, don't fold.
        if (width == 1)
          return {};
        APInt oneValue{width, 1ULL, /*isSigned=*/true};
        APInt minusOneValue{width, -1ULL, /*isSigned=*/true};

        if (power.isZero())
          return oneValue;

        if (power.isNegative()) {
          // Leave 0 raised to negative power not folded.
          if (base.isZero())
            return {};
          if (base.isOne())
            return oneValue;
          // If abs(base) > 1, then the result is zero.
          if (base.ne(minusOneValue))
            return zeroValue;
          // base == -1:
          //   -1: power is odd
          //    1: power is even
          if (power[0] == 1)
            return minusOneValue;

          return oneValue;
        }

        // power is positive.
        APInt result = oneValue;
        APInt curBase = base;
        APInt curPower = power;
        while (true) {
          if (curPower[0] == 1)
            result *= curBase;
          curPower.lshrInPlace(1);
          if (curPower.isZero())
            return result;
          curBase *= curBase;
        }
      });

  return Attribute();
}

//===----------------------------------------------------------------------===//
// LogOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::LogOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        if (a.isNegative())
          return {};

        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(log(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(logf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// Log2Op folder
//===----------------------------------------------------------------------===//

OpFoldResult math::Log2Op::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        if (a.isNegative())
          return {};

        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(log2(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(log2f(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// Log10Op folder
//===----------------------------------------------------------------------===//

OpFoldResult math::Log10Op::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        if (a.isNegative())
          return {};

        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(log10(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(log10f(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// Log1pOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::Log1pOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          if ((a + APFloat(1.0)).isNegative())
            return {};
          return APFloat(log1p(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          if ((a + APFloat(1.0f)).isNegative())
            return {};
          return APFloat(log1pf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// PowFOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::PowFOp::fold(FoldAdaptor adaptor) {
  return constFoldBinaryOpConditional<FloatAttr>(
      adaptor.getOperands(),
      [](const APFloat &a, const APFloat &b) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(pow(a.convertToDouble(), b.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(powf(a.convertToFloat(), b.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// RsqrtOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::RsqrtOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        if (a.isNegative())
          return {};

        APFloat one(a.getSemantics(), 1);
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return one / APFloat(sqrt(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return one / APFloat(sqrtf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// SqrtOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::SqrtOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        if (a.isNegative())
          return {};

        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(sqrt(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(sqrtf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// ExpOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::ExpOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(exp(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(expf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// Exp2Op folder
//===----------------------------------------------------------------------===//

OpFoldResult math::Exp2Op::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(exp2(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(exp2f(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// ExpM1Op folder
//===----------------------------------------------------------------------===//

OpFoldResult math::ExpM1Op::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(expm1(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(expm1f(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// IsFiniteOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::IsFiniteOp::fold(FoldAdaptor adaptor) {
  if (auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
    return BoolAttr::get(val.getContext(), val.getValue().isFinite());
  }
  if (auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
    return DenseElementsAttr::get(
        cast<ShapedType>(getType()),
        APInt(1, splat.getSplatValue<APFloat>().isFinite()));
  }
  return {};
}

//===----------------------------------------------------------------------===//
// IsInfOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::IsInfOp::fold(FoldAdaptor adaptor) {
  if (auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
    return BoolAttr::get(val.getContext(), val.getValue().isInfinity());
  }
  if (auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
    return DenseElementsAttr::get(
        cast<ShapedType>(getType()),
        APInt(1, splat.getSplatValue<APFloat>().isInfinity()));
  }
  return {};
}

//===----------------------------------------------------------------------===//
// IsNaNOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::IsNaNOp::fold(FoldAdaptor adaptor) {
  if (auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
    return BoolAttr::get(val.getContext(), val.getValue().isNaN());
  }
  if (auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
    return DenseElementsAttr::get(
        cast<ShapedType>(getType()),
        APInt(1, splat.getSplatValue<APFloat>().isNaN()));
  }
  return {};
}

//===----------------------------------------------------------------------===//
// IsNormalOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::IsNormalOp::fold(FoldAdaptor adaptor) {
  if (auto val = dyn_cast_or_null<FloatAttr>(adaptor.getOperand())) {
    return BoolAttr::get(val.getContext(), val.getValue().isNormal());
  }
  if (auto splat = dyn_cast_or_null<SplatElementsAttr>(adaptor.getOperand())) {
    return DenseElementsAttr::get(
        cast<ShapedType>(getType()),
        APInt(1, splat.getSplatValue<APFloat>().isNormal()));
  }
  return {};
}

//===----------------------------------------------------------------------===//
// TanOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::TanOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(tan(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(tanf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// TanhOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::TanhOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(tanh(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(tanhf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// RoundEvenOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::RoundEvenOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOp<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) {
        APFloat result(a);
        result.roundToIntegral(llvm::RoundingMode::NearestTiesToEven);
        return result;
      });
}

//===----------------------------------------------------------------------===//
// FloorOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::FloorOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOp<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) {
        APFloat result(a);
        result.roundToIntegral(llvm::RoundingMode::TowardNegative);
        return result;
      });
}

//===----------------------------------------------------------------------===//
// RoundOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::RoundOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(round(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(roundf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// TruncOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::TruncOp::fold(FoldAdaptor adaptor) {
  return constFoldUnaryOpConditional<FloatAttr>(
      adaptor.getOperands(), [](const APFloat &a) -> std::optional<APFloat> {
        switch (APFloat::SemanticsToEnum(a.getSemantics())) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(trunc(a.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(truncf(a.convertToFloat()));
        default:
          return {};
        }
      });
}

//===----------------------------------------------------------------------===//
// FPowIOp folder
//===----------------------------------------------------------------------===//

OpFoldResult math::FPowIOp::fold(FoldAdaptor adaptor) {
  return constFoldBinaryOpConditional<FloatAttr, IntegerAttr>(
      adaptor.getOperands(),
      [](const APFloat &base, const APInt &exp) -> std::optional<APFloat> {
        const llvm::fltSemantics &sem = base.getSemantics();
        // Fold when the exponent is exactly representable in the
        // floating-point type of the base.
        APFloat fExp(sem);
        if (fExp.convertFromAPInt(exp, /*isSigned=*/true,
                                  APFloat::rmNearestTiesToEven) !=
            APFloat::opOK)
          return {};

        switch (APFloat::SemanticsToEnum(sem)) {
        case APFloat::Semantics::S_IEEEdouble:
          return APFloat(pow(base.convertToDouble(), fExp.convertToDouble()));
        case APFloat::Semantics::S_IEEEsingle:
          return APFloat(powf(base.convertToFloat(), fExp.convertToFloat()));
        default:
          return {};
        }
      });
}

/// Materialize an integer or floating point constant.
Operation *math::MathDialect::materializeConstant(OpBuilder &builder,
                                                  Attribute value, Type type,
                                                  Location loc) {
  if (auto poison = dyn_cast<ub::PoisonAttr>(value))
    return ub::PoisonOp::create(builder, loc, type, poison);

  return arith::ConstantOp::materialize(builder, value, type, loc);
}
