/**
 * Copyright (c) 2026 Huawei Technologies Co., Ltd.
 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
 * CANN Open Software License Agreement Version 2.0 (the "License").
 * Please refer to the License for details. You may not use this file except in compliance with the License.
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
 * See LICENSE in the root of the software repository for the full text of the License.
 */

/**
 * ============================================================================
 * POW 算子测试用例说明
 * ============================================================================
 *
 * 一、正常测试用例
 * --------------------------------------------------------------------------
 * 1. 基础数据类型测试
 *    - DATA_TYPE_FLOAT_SUCC: Float 类型同形状计算
 *    - DATA_TYPE_INT8_SUCC: Int8 类型同形状计算
 *    - DATA_TYPE_INT32_SUCC: Int32 类型同形状计算
 *    - DATA_TYPE_INT64_SUCC: Int64 类型同形状计算
 *    - DATA_TYPE_DOUBLE_SUCC: Double 类型同形状计算
 *    - DATA_TYPE_COMPLEX64_SUCC: Complex64 类型同形状计算
 *    - DATA_TYPE_COMPLEX128_SUCC: Complex128 类型同形状计算
 *
 * 2. 广播场景测试
 *    - DATA_TYPE_FLOAT16_BROADCAST_SUCC: Float16 广播场景
 *    - DATA_TYPE_INT32_BROADCAST_SUCC: Int32 广播场景
 *
 * 3. 单元素广播测试
 *    - DATA_TYPE_ONE_X_ELEMENT_SUCC: X 单元素广播到 Y
 *    - DATA_TYPE_ONE_Y_ELEMENT_SUCC: Y 单元素广播到 X
 *
 * 4. 大张量测试
 *    - DATA_TYPE_NOBROADCAST_LARGE_35x1024: 大张量无广播 (35x1024)
 *    - DATA_TYPE_NOBROADCAST_LARGE_141x256: 大张量无广播 (141x256)
 *    - DATA_TYPE_BROADCAST_LARGE_30x1024: 大张量广播 (30x1024)
 *    - DATA_TYPE_FLOAT16_LARGE_100: Float16 大张量 (100)
 *    - DATA_TYPE_BROADCAST_FLOAT_100x24: Float 广播 (100x24)
 *    - DATA_TYPE_DOUBLE_LARGE_100: Double 大张量 (100)
 *    - DATA_TYPE_INT32_LARGE_100: Int32 大张量 (100)
 *    - DATA_TYPE_UINT8_LARGE_10x10x100: Uint8 大张量 (10x10x100)
 *
 * 5. 边界条件测试
 *    - FLOAT_SAME_SHAPE_SUCC: Float 同形状边界测试
 *    - FLOAT16_X_ONE_ELEMENT_SUCC: Float16 X 单元素边界测试
 *    - INT32_Y_ONE_ELEMENT_SUCC: Int32 Y 单元素边界测试
 *    - INT32_POWER_0_SUCC: Int32 零次幂边界测试
 *
 * 6. 类型转换宏测试
 *    - TYPE_CAST_DOUBLE_TO_FLOAT: Double 转 Float 类型转换
 *    - TYPE_CAST_FLOAT_TO_INT32: Float 转 Int32 类型转换
 *    - TYPE_CAST_INT32_TO_INT64: Int32 转 Int64 类型转换
 *    - TYPE_CAST_INT64_TO_INT32: Int64 转 Int32 类型转换
 *    - TYPE_CAST_INT8_TO_INT32: Int8 转 Int32 类型转换
 *    - TYPE_CAST_INT16_TO_INT64: Int16 转 Int64 类型转换
 *    - TYPE_CAST_UINT8_TO_INT64: Uint8 转 Int64 类型转换
 *
 * 7. 复数类型测试
 *    - RUN_POW_CASE_*: 复数类型组合测试
 *
 * --------------------------------------------------------------------------
 * 二、异常测试用例
 * --------------------------------------------------------------------------
 * 1. 输入异常
 *    - INPUT_NULL_EXCEPTION: 空指针输入异常
 *      测试场景: 输入张量指针为 nullptr 时应返回参数错误
 *    - INPUT_DTYPE_EXCEPTION: 数据类型不支持异常
 *      测试场景: 不支持的数据类型组合 (如 BOOL) 应返回参数错误
 *
 * 2. 形状异常
 *    - SHAPE_MISMATCH_EXCEPTION: 形状不匹配异常
 *      测试场景: 无法广播的不兼容形状应返回参数错误
 *
 * 3. 数值异常
 *    - NEGATIVE_EXPONENT_EXCEPTION: 负指数异常
 *      测试场景: 整数类型的负指数运算应返回参数错误
 *    - ZERO_NEGATIVE_POWER_EXCEPTION: 零的负次幂异常
 *      测试场景: 0 的负数次幂应返回参数错误 (避免除零)
 *
 * ============================================================================
 */

#include "gtest/gtest.h"
#ifndef private
#define private public
#define protected public
#endif
#include "utils/aicpu_test_utils.h"
#include "cpu_kernel_utils.h"
#include "node_def_builder.h"
#undef private
#undef protected
#include "Eigen/Core"
#include <iostream>


using namespace std;
using namespace aicpu;

class TEST_POW_UT : public testing::Test { };

#define CREATE_NODEDEF(shapes, data_types, datas)                  \
  auto node_def = CpuKernelUtils::CpuKernelUtils::CreateNodeDef(); \
  NodeDefBuilder(node_def.get(), "Pow", "Pow")                     \
      .Input({"x1", data_types[0], shapes[0], datas[0]})           \
      .Input({"x2", data_types[1], shapes[1], datas[1]})           \
      .Output({"y", data_types[2], shapes[2], datas[2]})

TEST_F(TEST_POW_UT, DATA_TYPE_FLOAT_SUCC) {
  vector<DataType> data_types = {DT_FLOAT, DT_FLOAT, DT_FLOAT};
  vector<vector<int64_t>> shapes = {{3, 3}, {3, 3}, {3, 3}};
  float input0[9] = {1.0f, 2.0f, 6.7f, 3.0f, 4.0f, 7.0f, 2.0f, 4.0f, 1.0f};
  float input1[9] = {2.0f, 2.0f, 3.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 2.0f};
  float output[9] = {0};
  float expect[9] = {1.0f, 4.0f, 300.763f, 3.0f, 4.0f, 7.0f, 2.0f, 1.0f, 1.0f};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (int i = 0; i < 9; ++i) {
    float absolute_error = std::fabs(output[i] - expect[i]);
    float relative_error = (expect[i] == 0) ? absolute_error : absolute_error / std::fabs(expect[i]);
    if ((absolute_error > 0.01f) && (relative_error > 0.01f)) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_FLOAT16_BROADCAST_SUCC) {
  vector<DataType> data_types = {DT_FLOAT16, DT_FLOAT16, DT_FLOAT16};
  vector<vector<int64_t>> shapes = {{3, 3}, {1, 3}, {3, 3}};
  Eigen::half input0[9] = {Eigen::half(1.0f), Eigen::half(2.0f), Eigen::half(3.0f),
                           Eigen::half(3.0f), Eigen::half(4.0f), Eigen::half(2.0f),
                           Eigen::half(2.0f), Eigen::half(4.0f), Eigen::half(1.0f)};
  Eigen::half input1[3] = {Eigen::half(2.0f), Eigen::half(2.0f), Eigen::half(2.0f)};
  Eigen::half output[9] = {Eigen::half(0.0f)};
  Eigen::half expect[9] = {Eigen::half(1.0f), Eigen::half(4.0f), Eigen::half(9.0f),
                           Eigen::half(9.0f), Eigen::half(16.0f), Eigen::half(4.0f),
                           Eigen::half(4.0f), Eigen::half(16.0f), Eigen::half(1.0f)};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (int i = 0; i < 9; ++i) {
    float out_val = static_cast<float>(output[i]);
    float exp_val = static_cast<float>(expect[i]);
    float absolute_error = std::fabs(out_val - exp_val);
    float relative_error = (exp_val == 0) ? absolute_error : absolute_error / std::fabs(exp_val);
    if ((absolute_error > 0.1f) && (relative_error > 0.01f)) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_INT32_BROADCAST_SUCC) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{3, 3}, {1, 3}, {3, 3}};
  int32_t input0[9] = {1, 2, 3, 4, 5, 6, 2, 4, 1};
  int32_t input1[3] = {2, 2, 2};
  int32_t output[9] = {0};
  int32_t expect[9] = {1, 4, 9, 16, 25, 36, 4, 16, 1};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool compare = CompareResult(output, expect, 9);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_INT64_SUCC) {
  vector<DataType> data_types = {DT_INT64, DT_INT64, DT_INT64};
  vector<vector<int64_t>> shapes = {{3, 3}, {3, 3}, {3, 3}};
  int64_t input0[9] = {1, 2, 7, 3, 4, 7, 2, 48, 1};
  int64_t input1[9] = {2, 2, 3, 8, 8, 5, 5, 2, 2};
  int64_t output[9] = {0};
  int64_t expect[9] = {1, 4, 343, 6561, 65536, 16807, 32, 2304, 1};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool compare = CompareResult(output, expect, 9);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_INT8_SUCC) {
  vector<DataType> data_types = {DT_INT8, DT_INT8, DT_INT8};
  vector<vector<int64_t>> shapes = {{2, 3}, {2, 3}, {2, 3}};
  int8_t input0[6] = {1, 2, 1, 3, 2, 2};
  int8_t input1[6] = {2, 2, 3, 1, 2, 2};
  int8_t output[6] = {0};
  int8_t expect[6] = {1, 4, 1, 3, 4, 4};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool compare = CompareResult(output, expect, 6);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_DOUBLE_SUCC) {
  vector<DataType> data_types = {DT_DOUBLE, DT_DOUBLE, DT_DOUBLE};
  vector<vector<int64_t>> shapes = {{2, 3}, {2, 3}, {2, 3}};
  double input0[6] = {1.0, 2.0, 3.0, 4.0, 5.0, 2.0};
  double input1[6] = {2.0, 2.0, 2.0, 2.0, 2.0, 2.0};
  double output[6] = {0};
  double expect[6] = {1.0, 4.0, 9.0, 16.0, 25.0, 4.0};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool compare = CompareResult(output, expect, 6);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_COMPLEX64_SUCC) {
  vector<DataType> data_types = {DT_COMPLEX64, DT_COMPLEX64, DT_COMPLEX64};
  vector<vector<int64_t>> shapes = {{2, 2}, {2, 2}, {2, 2}};
  std::complex<float> input0[4] = {std::complex<float>(2.0f, 0.0f), std::complex<float>(3.0f, 0.0f),
                                   std::complex<float>(2.0f, 0.0f), std::complex<float>(3.0f, 0.0f)};
  std::complex<float> input1[4] = {std::complex<float>(2.0f, 0.0f), std::complex<float>(2.0f, 0.0f),
                                    std::complex<float>(2.0f, 0.0f), std::complex<float>(2.0f, 0.0f)};
  std::complex<float> output[4] = {std::complex<float>(0.0f, 0.0f)};
  std::complex<float> expect[4] = {std::complex<float>(4.0f, 0.0f), std::complex<float>(9.0f, 0.0f),
                                    std::complex<float>(4.0f, 0.0f), std::complex<float>(9.0f, 0.0f)};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (int i = 0; i < 4; ++i) {
    float absolute_error = std::abs(output[i] - expect[i]);
    if (absolute_error > 0.001f) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_COMPLEX128_SUCC) {
  vector<DataType> data_types = {DT_COMPLEX128, DT_COMPLEX128, DT_COMPLEX128};
  vector<vector<int64_t>> shapes = {{2, 2}, {2, 2}, {2, 2}};
  std::complex<double> input0[4] = {std::complex<double>(2.0, 0.0), std::complex<double>(3.0, 0.0),
                                     std::complex<double>(2.0, 0.0), std::complex<double>(3.0, 0.0)};
  std::complex<double> input1[4] = {std::complex<double>(2.0, 0.0), std::complex<double>(2.0, 0.0),
                                     std::complex<double>(2.0, 0.0), std::complex<double>(2.0, 0.0)};
  std::complex<double> output[4] = {std::complex<double>(0.0, 0.0)};
  std::complex<double> expect[4] = {std::complex<double>(4.0, 0.0), std::complex<double>(9.0, 0.0),
                                     std::complex<double>(4.0, 0.0), std::complex<double>(9.0, 0.0)};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (int i = 0; i < 4; ++i) {
    double absolute_error = std::abs(output[i] - expect[i]);
    if (absolute_error > 0.001) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_ONE_X_ELEMENT_SUCC) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{4, 2}, {}, {4, 2}};
  int32_t input0[8] = {1, 2, 2, 1, 2, 1, 2, 1};
  int32_t input1[1] = {3};
  int32_t output[8] = {0};
  int32_t expect[8] = {1, 8, 8, 1, 8, 1, 8, 1};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool compare = CompareResult(output, expect, 8);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_ONE_Y_ELEMENT_SUCC) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{}, {2, 3}, {2, 3}};
  int32_t input0[1] = {2};
  int32_t input1[6] = {1, 2, 7, 2, 8, 1};
  int32_t output[6] = {0};
  int32_t expect[6] = {2, 4, 128, 4, 256, 2};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool compare = CompareResult(output, expect, 6);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_NOBROADCAST_LARGE_35x1024) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{35, 1024}, {35, 1024}, {35, 1024}};
  int32_t input0[35840];
  int32_t input1[35840];
  int32_t output[35840];
  for (size_t i = 0; i < 35840; ++i) {
    input0[i] = (i % 10) + 1;
    input1[i] = (i % 3) + 1;
  }
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (size_t i = 0; i < 35840; ++i) {
    int32_t expected = 1;
    for (int j = 0; j < input1[i]; ++j) {
      expected *= input0[i];
    }
    if (output[i] != expected) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_NOBROADCAST_LARGE_141x256) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{141, 256}, {141, 256}, {141, 256}};
  int32_t input0[36096];
  int32_t input1[36096];
  int32_t output[36096];
  for (size_t i = 0; i < 36096; ++i) {
    input0[i] = (i % 5) + 1;
    input1[i] = (i % 2) + 1;
  }
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (size_t i = 0; i < 36096; ++i) {
    int32_t expected = 1;
    for (int j = 0; j < input1[i]; ++j) {
      expected *= input0[i];
    }
    if (output[i] != expected) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_BROADCAST_LARGE_30x1024) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{30, 1024}, {1024}, {30, 1024}};
  int32_t input0[30720];
  int32_t input1[1024];
  int32_t output[30720];
  for (size_t i = 0; i < 30720; ++i) {
    input0[i] = (i % 10) + 1;
  }
  for (size_t i = 0; i < 1024; ++i) {
    input1[i] = (i % 3) + 1;
  }
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (size_t i = 0; i < 30720; ++i) {
    int32_t expected = 1;
    int32_t y = input1[i % 1024];
    for (int j = 0; j < y; ++j) {
      expected *= input0[i];
    }
    if (output[i] != expected) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_FLOAT16_LARGE_100) {
  vector<DataType> data_types = {DT_FLOAT16, DT_FLOAT16, DT_FLOAT16};
  vector<vector<int64_t>> shapes = {{100}, {100}, {100}};
  Eigen::half input0[100];
  Eigen::half input1[100];
  Eigen::half output[100];
  for (size_t i = 0; i < 100; ++i) {
    input0[i] = Eigen::half(static_cast<float>((i % 5) + 1));
    input1[i] = Eigen::half(static_cast<float>((i % 3) + 1));
  }
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (size_t i = 0; i < 100; ++i) {
    float expected = powf(static_cast<float>(input0[i]), static_cast<float>(input1[i]));
    float actual = static_cast<float>(output[i]);
    if (std::fabs(expected - actual) > 0.01f) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_BROADCAST_FLOAT_100x24) {
  vector<DataType> data_types = {DT_FLOAT, DT_FLOAT, DT_FLOAT};
  vector<vector<int64_t>> shapes = {{100, 24}, {24}, {100, 24}};
  float input0[2400];
  float input1[24];
  float output[2400];
  for (size_t i = 0; i < 2400; ++i) {
    input0[i] = static_cast<float>((i % 5) + 1);
  }
  for (size_t i = 0; i < 24; ++i) {
    input1[i] = static_cast<float>((i % 3) + 1);
  }
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (size_t i = 0; i < 2400; ++i) {
    float expected = powf(input0[i], input1[i % 24]);
    if (std::fabs(output[i] - expected) > 0.01f) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_DOUBLE_LARGE_100) {
  vector<DataType> data_types = {DT_DOUBLE, DT_DOUBLE, DT_DOUBLE};
  vector<vector<int64_t>> shapes = {{100}, {100}, {100}};
  double input0[100];
  double input1[100];
  double output[100];
  for (size_t i = 0; i < 100; ++i) {
    input0[i] = static_cast<double>((i % 5) + 1);
    input1[i] = static_cast<double>((i % 3) + 1);
  }
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (size_t i = 0; i < 100; ++i) {
    double expected = pow(input0[i], input1[i]);
    if (std::fabs(output[i] - expected) > 0.0001) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_INT32_LARGE_100) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{100}, {100}, {100}};
  int32_t input0[100];
  int32_t input1[100];
  int32_t output[100];
  for (size_t i = 0; i < 100; ++i) {
    input0[i] = (i % 5) + 1;
    input1[i] = (i % 3) + 1;
  }
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (size_t i = 0; i < 100; ++i) {
    int32_t expected = 1;
    for (int j = 0; j < input1[i]; ++j) {
      expected *= input0[i];
    }
    if (output[i] != expected) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, DATA_TYPE_UINT8_LARGE_10x10x100) {
  vector<DataType> data_types = {DT_UINT8, DT_UINT8, DT_UINT8};
  vector<vector<int64_t>> shapes = {{10, 10, 100}, {10, 10, 100}, {10, 10, 100}};
  uint8_t input0[10000];
  uint8_t input1[10000];
  uint8_t output[10000];
  for (size_t i = 0; i < 10000; ++i) {
    input0[i] = (i % 4) + 1;
    input1[i] = (i % 2) + 1;
  }
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  bool result = true;
  for (size_t i = 0; i < 10000; ++i) {
    uint8_t expected = 1;
    for (int j = 0; j < input1[i]; ++j) {
      expected *= input0[i];
    }
    if (output[i] != expected) {
      result = false;
      break;
    }
  }
  EXPECT_EQ(result, true);
}

TEST_F(TEST_POW_UT, INPUT_NULL_EXCEPTION) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
 vector<vector<int64_t>> shapes = {{4,4},{4,4},{4,4}};
 int8_t input0[16]={(int32_t)0};
 int8_t input1[16]={(int32_t)0};
 int8_t output[16]={(int32_t)0};
 vector<void *> datas = {(void *)nullptr,(void *)nullptr, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_PARAM_INVALID);
}

TEST_F(TEST_POW_UT, INPUT_DTYPE_EXCEPTION) {
  vector<DataType> data_types = {DT_BOOL, DT_BOOL, DT_BOOL};
  vector<vector<int64_t>> shapes = {{1,2},{2,2},{2,2}};
  bool input0[2]={0,0};
  bool input1[4]={0,1,0,1};
  bool output[4]={0,1,0,1};
  vector<void *> datas = {(void *)input0,(void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_PARAM_INVALID);
}

TEST_F(TEST_POW_UT, OUTPUT_NULL_EXCEPTION) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{4,4},{4,4},{4,4}};
  int32_t input0[16]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
  int32_t input1[16]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
  vector<void *> datas = {(void *)input0,(void *)input1, (void *)nullptr};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_PARAM_INVALID);
}

TEST_F(TEST_POW_UT, NEGATIVE_EXPONENT_EXCEPTION) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{3},{3},{3}};
  int32_t input0[3]={2,3,4};
  int32_t input1[3]={-1,-2,-3};
  int32_t output[3]={0};
  vector<void *> datas = {(void *)input0,(void *)input1,(void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
}

TEST_F(TEST_POW_UT, ZERO_NEGATIVE_POWER_EXCEPTION) {
  vector<DataType> data_types = {DT_FLOAT, DT_FLOAT, DT_FLOAT};
  vector<vector<int64_t>> shapes = {{3},{3},{3}};
  float input0[3]={0.0f,0.0f,0.0f};
  float input1[3]={-1.0f,-2.0f,-3.0f};
  float output[3]={0};
  vector<void *> datas = {(void *)input0,(void *)input1,(void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
}

TEST_F(TEST_POW_UT, INPUT_X_NULL_EXCEPTION) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{4,4},{4,4},{4,4}};
  int32_t input1[16]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
  int32_t output[16]={0};
  vector<void *> datas = {(void *)nullptr,(void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_PARAM_INVALID);
}

TEST_F(TEST_POW_UT, INPUT_Y_NULL_EXCEPTION) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{4,4},{4,4},{4,4}};
  int32_t input0[16]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
  int32_t output[16]={0};
  vector<void *> datas = {(void *)input0,(void *)nullptr, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_PARAM_INVALID);
}

TEST_F(TEST_POW_UT, EMPTY_SHAPE_EXCEPTION) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{0},{1},{1}};
  int32_t input1[1]={1};
  int32_t output[1]={0};
  vector<void *> datas = {(void *)nullptr,(void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
}

TEST_F(TEST_POW_UT, FLOAT_SAME_SHAPE_SUCC) {
  vector<DataType> data_types = {DT_FLOAT, DT_FLOAT, DT_FLOAT};
  vector<vector<int64_t>> shapes = {{3}, {3}, {3}};
  float input0[3] = {2.0f, 3.0f, 4.0f};
  float input1[3] = {2.0f, 2.0f, 2.0f};
  float output[3] = {0};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  float expect[3] = {4.0f, 9.0f, 16.0f};
  bool compare = CompareResult(output, expect, 3);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, FLOAT16_X_ONE_ELEMENT_SUCC) {
  vector<DataType> data_types = {DT_FLOAT16, DT_FLOAT16, DT_FLOAT16};
  vector<vector<int64_t>> shapes = {{}, {3}, {3}};
  Eigen::half input0[1] = {Eigen::half(2.0f)};
  Eigen::half input1[3] = {Eigen::half(2.0f), Eigen::half(3.0f), Eigen::half(4.0f)};
  Eigen::half output[3] = {Eigen::half(0.0f)};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  Eigen::half expect[3] = {Eigen::half(4.0f), Eigen::half(8.0f), Eigen::half(16.0f)};
  bool compare = CompareResult(output, expect, 3);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, INT32_Y_ONE_ELEMENT_SUCC) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{3}, {}, {3}};
  int32_t input0[3] = {2, 3, 4};
  int32_t input1[1] = {2};
  int32_t output[3] = {0};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  int32_t expect[3] = {4, 9, 16};
  bool compare = CompareResult(output, expect, 3);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, INT32_POWER_0_SUCC) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{3}, {3}, {3}};
  int32_t input0[3] = {2, 3, 4};
  int32_t input1[3] = {0, 0, 0};
  int32_t output[3] = {0};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  int32_t expect[3] = {1, 1, 1};
  bool compare = CompareResult(output, expect, 3);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, INT32_POWER_1_SUCC) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{3}, {3}, {3}};
  int32_t input0[3] = {2, 3, 4};
  int32_t input1[3] = {1, 1, 1};
  int32_t output[3] = {0};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  int32_t expect[3] = {2, 3, 4};
  bool compare = CompareResult(output, expect, 3);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, INT32_POWER_NEGATIVE_1_SUCC) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{3}, {3}, {3}};
  int32_t input0[3] = {-1, -1, -1};
  int32_t input1[3] = {-2, -3, -4};
  int32_t output[3] = {0};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  int32_t expect[3] = {1, -1, 1};
  bool compare = CompareResult(output, expect, 3);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, INT32_POWER_NEGATIVE_OTHER_SUCC) {
  vector<DataType> data_types = {DT_INT32, DT_INT32, DT_INT32};
  vector<vector<int64_t>> shapes = {{3}, {3}, {3}};
  int32_t input0[3] = {2, 3, 4};
  int32_t input1[3] = {-2, -3, -4};
  int32_t output[3] = {0};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
  int32_t expect[3] = {0, 0, 0};
  bool compare = CompareResult(output, expect, 3);
  EXPECT_EQ(compare, true);
}

TEST_F(TEST_POW_UT, EMPTY_TENSOR_SUCC) {
  vector<DataType> data_types = {DT_FLOAT, DT_FLOAT, DT_FLOAT};
  vector<vector<int64_t>> shapes = {{0}, {0}, {0}};
  float input0[1] = {0};
  float input1[1] = {0};
  float output[1] = {0};
  vector<void *> datas = {(void *)input0, (void *)input1, (void *)output};
  CREATE_NODEDEF(shapes, data_types, datas);
  RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);
}

#define RUN_POW_CASE(base_type_in1, base_type_in2, base_type_out,                            \
                     aicpu_type_in1, aicpu_type_in2, aicpu_type_out)                         \
  TEST_F(TEST_POW_UT, TestCast_##aicpu_type_in1##aicpu_type_in2####aicpu_type_out) {         \
      vector<DataType> data_types = {aicpu_type_in1, aicpu_type_in2, aicpu_type_out};        \
      base_type_in1 input1[3] = {(base_type_in1)2, (base_type_in1)3, (base_type_in1)4};      \
      base_type_in2 input2[1] = {(base_type_in2)2};                                          \
      base_type_out output[3] = {};                                                          \
      vector<void *> datas = {(void *)input1, (void *)input2, (void *)output};               \
      vector<vector<int64_t>> shapes = {{3}, {}, {3}};                                       \
      CREATE_NODEDEF(shapes, data_types, datas);                                             \
      RUN_KERNEL(node_def, HOST, KERNEL_STATUS_OK);                                          \
      base_type_out expect_out[3] = {(base_type_out)4, (base_type_out)9, (base_type_out)16}; \
      EXPECT_EQ(CompareResult<base_type_out>(output, expect_out, 3), true);                  \
  }

RUN_POW_CASE(int8_t, int8_t, int8_t, DT_INT8, DT_INT8, DT_INT8);
RUN_POW_CASE(int8_t, int16_t, int8_t, DT_INT8, DT_INT16, DT_INT8);
RUN_POW_CASE(int8_t, int16_t, int16_t, DT_INT8, DT_INT16, DT_INT16);
RUN_POW_CASE(int8_t, int32_t, int8_t, DT_INT8, DT_INT32, DT_INT8);
RUN_POW_CASE(int8_t, int32_t, int32_t, DT_INT8, DT_INT32, DT_INT32);
RUN_POW_CASE(int8_t, int64_t, int8_t, DT_INT8, DT_INT64, DT_INT8);
RUN_POW_CASE(int8_t, int64_t, int64_t, DT_INT8, DT_INT64, DT_INT64);
RUN_POW_CASE(int8_t, uint8_t, int8_t, DT_INT8, DT_UINT8, DT_INT8);
RUN_POW_CASE(int8_t, uint8_t, int16_t, DT_INT8, DT_UINT8, DT_INT16);
RUN_POW_CASE(int8_t, Eigen::half, Eigen::half, DT_INT8, DT_FLOAT16, DT_FLOAT16);
RUN_POW_CASE(int8_t, float, float, DT_INT8, DT_FLOAT, DT_FLOAT);
RUN_POW_CASE(int8_t, double, double, DT_INT8, DT_DOUBLE, DT_DOUBLE);
RUN_POW_CASE(int8_t, std::complex<float>, std::complex<float>, DT_INT8, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(int8_t, std::complex<double>, std::complex<double>, DT_INT8, DT_COMPLEX128, DT_COMPLEX128);

RUN_POW_CASE(int16_t, int8_t, int16_t, DT_INT16, DT_INT8, DT_INT16);
RUN_POW_CASE(int16_t, int16_t, int16_t, DT_INT16, DT_INT16, DT_INT16);
RUN_POW_CASE(int16_t, int32_t, int16_t, DT_INT16, DT_INT32, DT_INT16);
RUN_POW_CASE(int16_t, int32_t, int32_t, DT_INT16, DT_INT32, DT_INT32);
RUN_POW_CASE(int16_t, int64_t, int16_t, DT_INT16, DT_INT64, DT_INT16);
RUN_POW_CASE(int16_t, int64_t, int64_t, DT_INT16, DT_INT64, DT_INT64);
RUN_POW_CASE(int16_t, uint8_t, int16_t, DT_INT16, DT_UINT8, DT_INT16);
RUN_POW_CASE(int16_t, Eigen::half, Eigen::half, DT_INT16, DT_FLOAT16, DT_FLOAT16);
RUN_POW_CASE(int16_t, Eigen::half, int16_t, DT_INT16, DT_FLOAT16, DT_INT16);
RUN_POW_CASE(int16_t, float, float, DT_INT16, DT_FLOAT, DT_FLOAT);
RUN_POW_CASE(int16_t, float, int16_t, DT_INT16, DT_FLOAT, DT_INT16);
RUN_POW_CASE(int16_t, double, double, DT_INT16, DT_DOUBLE, DT_DOUBLE);
RUN_POW_CASE(int16_t, double, int16_t, DT_INT16, DT_DOUBLE, DT_INT16);
RUN_POW_CASE(int16_t, std::complex<float>, std::complex<float>, DT_INT16, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(int16_t, std::complex<float>, int16_t, DT_INT16, DT_COMPLEX64, DT_INT16);
RUN_POW_CASE(int16_t, std::complex<double>, std::complex<double>, DT_INT16, DT_COMPLEX128, DT_COMPLEX128);
RUN_POW_CASE(int16_t, std::complex<double>, int16_t, DT_INT16, DT_COMPLEX128, DT_INT16);

RUN_POW_CASE(int32_t, int8_t, int32_t, DT_INT32, DT_INT8, DT_INT32);
RUN_POW_CASE(int32_t, int16_t, int32_t, DT_INT32, DT_INT16, DT_INT32);
RUN_POW_CASE(int32_t, int32_t, int32_t, DT_INT32, DT_INT32, DT_INT32);
RUN_POW_CASE(int32_t, int64_t, int32_t, DT_INT32, DT_INT64, DT_INT32);
RUN_POW_CASE(int32_t, int64_t, int64_t, DT_INT32, DT_INT64, DT_INT64);
RUN_POW_CASE(int32_t, uint8_t, int32_t, DT_INT32, DT_UINT8, DT_INT32);
RUN_POW_CASE(int32_t, Eigen::half, Eigen::half, DT_INT32, DT_FLOAT16, DT_FLOAT16);
RUN_POW_CASE(int32_t, float, float, DT_INT32, DT_FLOAT, DT_FLOAT);
RUN_POW_CASE(int32_t, double, double, DT_INT32, DT_DOUBLE, DT_DOUBLE);
RUN_POW_CASE(int32_t, std::complex<float>, std::complex<float>, DT_INT32, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(int32_t, std::complex<double>, std::complex<double>, DT_INT32, DT_COMPLEX128, DT_COMPLEX128);

RUN_POW_CASE(int64_t, int8_t, int64_t, DT_INT64, DT_INT8, DT_INT64);
RUN_POW_CASE(int64_t, int16_t, int64_t, DT_INT64, DT_INT16, DT_INT64);
RUN_POW_CASE(int64_t, int32_t, int64_t, DT_INT64, DT_INT32, DT_INT64);
RUN_POW_CASE(int64_t, int64_t, int64_t, DT_INT64, DT_INT64, DT_INT64);
RUN_POW_CASE(int64_t, uint8_t, int64_t, DT_INT64, DT_UINT8, DT_INT64);
RUN_POW_CASE(int64_t, Eigen::half, Eigen::half, DT_INT64, DT_FLOAT16, DT_FLOAT16);
RUN_POW_CASE(int64_t, float, float, DT_INT64, DT_FLOAT, DT_FLOAT);
RUN_POW_CASE(int64_t, double, double, DT_INT64, DT_DOUBLE, DT_DOUBLE);
RUN_POW_CASE(int64_t, std::complex<float>, std::complex<float>, DT_INT64, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(int64_t, std::complex<double>, std::complex<double>, DT_INT64, DT_COMPLEX128, DT_COMPLEX128);

RUN_POW_CASE(uint8_t, int8_t, uint8_t, DT_UINT8, DT_INT8, DT_UINT8);
RUN_POW_CASE(uint8_t, int8_t, int16_t, DT_UINT8, DT_INT8, DT_INT16);
RUN_POW_CASE(uint8_t, int16_t, uint8_t, DT_UINT8, DT_INT16, DT_UINT8);
RUN_POW_CASE(uint8_t, int16_t, int16_t, DT_UINT8, DT_INT16, DT_INT16);
RUN_POW_CASE(uint8_t, int32_t, uint8_t, DT_UINT8, DT_INT32, DT_UINT8);
RUN_POW_CASE(uint8_t, int32_t, int32_t, DT_UINT8, DT_INT32, DT_INT32);
RUN_POW_CASE(uint8_t, int64_t, uint8_t, DT_UINT8, DT_INT64, DT_UINT8);
RUN_POW_CASE(uint8_t, int64_t, int64_t, DT_UINT8, DT_INT64, DT_INT64);
RUN_POW_CASE(uint8_t, uint8_t, uint8_t, DT_UINT8, DT_UINT8, DT_UINT8);
RUN_POW_CASE(uint8_t, Eigen::half, Eigen::half, DT_UINT8, DT_FLOAT16, DT_FLOAT16);
RUN_POW_CASE(uint8_t, float, float, DT_UINT8, DT_FLOAT, DT_FLOAT);
RUN_POW_CASE(uint8_t, double, double, DT_UINT8, DT_DOUBLE, DT_DOUBLE);
RUN_POW_CASE(uint8_t, std::complex<float>, std::complex<float>, DT_UINT8, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(uint8_t, std::complex<double>, std::complex<double>, DT_UINT8, DT_COMPLEX128, DT_COMPLEX128);

RUN_POW_CASE(Eigen::half, int8_t, Eigen::half, DT_FLOAT16, DT_INT8, DT_FLOAT16);
RUN_POW_CASE(Eigen::half, int16_t, Eigen::half, DT_FLOAT16, DT_INT16, DT_FLOAT16);
RUN_POW_CASE(Eigen::half, int32_t, Eigen::half, DT_FLOAT16, DT_INT32, DT_FLOAT16);
RUN_POW_CASE(Eigen::half, int64_t, Eigen::half, DT_FLOAT16, DT_INT64, DT_FLOAT16);
RUN_POW_CASE(Eigen::half, uint8_t, Eigen::half, DT_FLOAT16, DT_UINT8, DT_FLOAT16);
RUN_POW_CASE(Eigen::half, Eigen::half, Eigen::half, DT_FLOAT16, DT_FLOAT16, DT_FLOAT16);
RUN_POW_CASE(Eigen::half, float, Eigen::half, DT_FLOAT16, DT_FLOAT, DT_FLOAT16);
RUN_POW_CASE(Eigen::half, float, float, DT_FLOAT16, DT_FLOAT, DT_FLOAT);
RUN_POW_CASE(Eigen::half, double, Eigen::half, DT_FLOAT16, DT_DOUBLE, DT_FLOAT16);
RUN_POW_CASE(Eigen::half, double, double, DT_FLOAT16, DT_DOUBLE, DT_DOUBLE);
RUN_POW_CASE(Eigen::half, std::complex<float>, std::complex<float>, DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(Eigen::half, std::complex<double>, std::complex<double>, DT_FLOAT16, DT_COMPLEX128, DT_COMPLEX128);

RUN_POW_CASE(float, int8_t, float, DT_FLOAT, DT_INT8, DT_FLOAT);
RUN_POW_CASE(float, int16_t, float, DT_FLOAT, DT_INT16, DT_FLOAT);
RUN_POW_CASE(float, int32_t, float, DT_FLOAT, DT_INT32, DT_FLOAT);
RUN_POW_CASE(float, int64_t, float, DT_FLOAT, DT_INT64, DT_FLOAT);
RUN_POW_CASE(float, uint8_t, float, DT_FLOAT, DT_UINT8, DT_FLOAT);
RUN_POW_CASE(float, Eigen::half, float, DT_FLOAT, DT_FLOAT16, DT_FLOAT);
RUN_POW_CASE(float, float, float, DT_FLOAT, DT_FLOAT, DT_FLOAT);
RUN_POW_CASE(float, double, float, DT_FLOAT, DT_DOUBLE, DT_FLOAT);
RUN_POW_CASE(float, double, double, DT_FLOAT, DT_DOUBLE, DT_DOUBLE);
RUN_POW_CASE(float, std::complex<float>, std::complex<float>, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(float, std::complex<double>, std::complex<double>, DT_FLOAT, DT_COMPLEX128, DT_COMPLEX128);

RUN_POW_CASE(double, int8_t, double, DT_DOUBLE, DT_INT8, DT_DOUBLE);
RUN_POW_CASE(double, int16_t, double, DT_DOUBLE, DT_INT16, DT_DOUBLE);
RUN_POW_CASE(double, int32_t, double, DT_DOUBLE, DT_INT32, DT_DOUBLE);
RUN_POW_CASE(double, int64_t, double, DT_DOUBLE, DT_INT64, DT_DOUBLE);
RUN_POW_CASE(double, uint8_t, double, DT_DOUBLE, DT_UINT8, DT_DOUBLE);
RUN_POW_CASE(double, Eigen::half, double, DT_DOUBLE, DT_FLOAT16, DT_DOUBLE);
RUN_POW_CASE(double, float, double, DT_DOUBLE, DT_FLOAT, DT_DOUBLE);
RUN_POW_CASE(double, double, double, DT_DOUBLE, DT_DOUBLE, DT_DOUBLE);
RUN_POW_CASE(double, std::complex<float>, std::complex<float>, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(double, std::complex<float>, std::complex<double>, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128);
RUN_POW_CASE(double, std::complex<double>, std::complex<double>, DT_DOUBLE, DT_COMPLEX128, DT_COMPLEX128);

RUN_POW_CASE(std::complex<float>, int8_t, std::complex<float>, DT_COMPLEX64, DT_INT8, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, int16_t, std::complex<float>, DT_COMPLEX64, DT_INT16, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, int32_t, std::complex<float>, DT_COMPLEX64, DT_INT32, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, int64_t, std::complex<float>, DT_COMPLEX64, DT_INT64, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, uint8_t, std::complex<float>, DT_COMPLEX64, DT_UINT8, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, Eigen::half, std::complex<float>, DT_COMPLEX64, DT_FLOAT16, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, float, std::complex<float>, DT_COMPLEX64, DT_FLOAT, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, double, std::complex<float>, DT_COMPLEX64, DT_DOUBLE, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, double, std::complex<double>, DT_COMPLEX64, DT_DOUBLE, DT_COMPLEX128);
RUN_POW_CASE(std::complex<float>, std::complex<float>, std::complex<float>, DT_COMPLEX64, DT_COMPLEX64, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, std::complex<double>, std::complex<float>, DT_COMPLEX64, DT_COMPLEX128, DT_COMPLEX64);
RUN_POW_CASE(std::complex<float>, std::complex<double>, std::complex<double>, DT_COMPLEX64, DT_COMPLEX128, DT_COMPLEX128);

RUN_POW_CASE(std::complex<double>, int8_t, std::complex<double>, DT_COMPLEX128, DT_INT8, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, int16_t, std::complex<double>, DT_COMPLEX128, DT_INT16, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, int32_t, std::complex<double>, DT_COMPLEX128, DT_INT32, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, int64_t, std::complex<double>, DT_COMPLEX128, DT_INT64, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, uint8_t, std::complex<double>, DT_COMPLEX128, DT_UINT8, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, Eigen::half, std::complex<double>, DT_COMPLEX128, DT_FLOAT16, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, float, std::complex<double>, DT_COMPLEX128, DT_FLOAT, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, double, std::complex<double>, DT_COMPLEX128, DT_DOUBLE, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, std::complex<float>, std::complex<double>, DT_COMPLEX128, DT_COMPLEX64, DT_COMPLEX128);
RUN_POW_CASE(std::complex<double>, std::complex<double>, std::complex<double>, DT_COMPLEX128, DT_COMPLEX128, DT_COMPLEX128);