// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include "paddle/ap/include/axpr/binary_func.h" #include "paddle/ap/include/axpr/data_type.h" #include "paddle/ap/include/axpr/data_value.h" #include "paddle/ap/include/axpr/unary_func.h" namespace ap::axpr { namespace detail { template struct ArithmeticUnaryFuncHelper { static Result Call(const DataValue& value) { return value.Match([](auto val) -> Result { if constexpr (IsArithmeticOpSupported()) { return ArithmeticOp::Call(val); } else { return adt::errors::TypeError{ std::string() + "unsupported operand type for " + ArithmeticOp::Name() + ": " + CppDataType{}.Name() + "."}; } }); } }; template struct ArithmeticBinaryOpHelper { template static Result Call(LhsT lhs, RhsT rhs) { return ArithmeticOp::Call(lhs, rhs); } }; template <> struct ArithmeticBinaryOpHelper { template static Result Call(LhsT lhs, RhsT rhs) { if (rhs == 0) { return adt::errors::ZeroDivisionError{"division or modulo by zero"}; } return ArithmeticDiv::Call(lhs, rhs); } }; template <> struct ArithmeticBinaryOpHelper { template static Result Call(LhsT lhs, RhsT rhs) { if constexpr (std::is_integral_v && std::is_integral_v) { if (rhs == 0) { return adt::errors::ZeroDivisionError{"division or modulo by zero"}; } return ArithmeticMod::Call(lhs, rhs); } else { return adt::errors::TypeError{ std::string() + "'%' only support integral type, but receive: '" + CppDataType{}.Name() + "' and '" + CppDataType{}.Name() + "'."}; } } }; template struct ArithmeticBinaryFuncHelper { static Result Call(const DataValue& lhs_value, const DataValue& rhs_value) { const auto& pattern_match = ::common::Overloaded{[](auto lhs, auto rhs) -> Result { if constexpr (IsArithmeticOpSupported() && IsArithmeticOpSupported()) { return ArithmeticBinaryOpHelper::Call(lhs, rhs); } else { return adt::errors::TypeError{ std::string() + "unsupported operand types for " + ArithmeticOp::Name() + ": '" + CppDataType{}.Name() + "' and '" + CppDataType{}.Name() + "'."}; } }}; return std::visit(pattern_match, lhs_value.variant(), rhs_value.variant()); } }; } // namespace detail template Result ArithmeticUnaryFunc(const DataValue& value) { return detail::ArithmeticUnaryFuncHelper::Call(value); } template Result ArithmeticBinaryFunc(const DataValue& lhs_value, const DataValue& rhs_value) { return detail::ArithmeticBinaryFuncHelper::Call(lhs_value, rhs_value); } } // namespace ap::axpr