diff --git a/dxlibex/basic_types/point2d.hpp b/dxlibex/basic_types/point2d.hpp index 0c5d38d..d2a8a3f 100644 --- a/dxlibex/basic_types/point2d.hpp +++ b/dxlibex/basic_types/point2d.hpp @@ -624,7 +624,40 @@ namespace dxle { { return p1.x * p2.x + p1.y * p2.y; } - + namespace detail { + template::value, bool is_signed = std::is_signed::value, std::size_t sizeof_T = sizeof(T)> + struct point_c_mem_cross_helper_integral { using type = T; }; + template struct point_c_mem_cross_helper_integral { using type = std::int16_t; }; + template struct point_c_mem_cross_helper_integral { using type = std::uint16_t; }; + template struct point_c_mem_cross_helper_integral { using type = std::int32_t; }; + template struct point_c_mem_cross_helper_integral { using type = std::uint32_t; }; + template struct point_c_mem_cross_helper_integral { using type = std::int64_t; }; + template struct point_c_mem_cross_helper_integral { using type = std::uint64_t; }; + template struct point_c_mem_cross_helper_integral { using type = std::int64_t; }; + template struct point_c_mem_cross_helper_integral { using type = std::uint64_t; }; + + template< + typename T1, typename T2, + bool both_arithmetic = std::is_arithmetic::value && std::is_arithmetic::value, + bool T1_is_integral = std::is_integral::value, + bool T2_is_integral = std::is_integral::value, + bool T1_or_T2_is_floating_point = std::is_floating_point::value || std::is_floating_point::value + > + struct point_c_mem_cross_helper { using type = T1; }; + template + struct point_c_mem_cross_helper { using type = double; }; + template struct point_c_mem_cross_helper : point_c_mem_cross_helper_integral {}; + template struct point_c_mem_cross_helper : point_c_mem_cross_helper_integral {}; + template struct point_c_mem_cross_helper : point_c_mem_cross_helper_integral {}; + template struct point_c_mem_cross_helper : point_c_mem_cross_helper_integral< + typename std::conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type, true, std::is_signed::value || std::is_signed::value + > {}; + template struct point_c_mem_cross_helper { using type = T2; }; + template struct point_c_mem_cross_helper { using type = T1; }; + + template + using point_c_mem_cross_helper_result_type = typename point_c_mem_cross_helper::type; + } /** @relates point_c \~japanese @brief 2つのpoint_cクラスオブジェクトをベクトルとして外積を計算する @@ -634,16 +667,28 @@ namespace dxle { \~japanese @param p2 point_cクラスオブジェクト \~english @param p2 point_c value \~japanese @return 計算結果。 + (T1 : 第1引数の型, T2 : 第2引数の型) + 戻り値の型 + 1. T1もしくはT2がarithmeticではない場合、arithmeticではない方(T1が優先) + 2. T1もしくはT2が浮動小数点型の場合、double + 3. T1もしくはT2が整数型の場合、大きい方の型の倍の大きさの整数型 + 4. いずれでもない時はT1 \~english @return Computed result. + (T1 : first argumrnt type, T2 : second argumet type) + result type : + 1. when T1 or T2 is not arithemtic type, result type is not-arithmetic one(T1 has high pritority). + 2. when T1 or T2 is floating point type, result type is double. + 3. when T1 or T2 is integral type, result type is integral type. sizeof(result type) is twice as many size as bigger one. + 4. In other case, result type is T1. */ - template - DXLE_CONSTEXPR double cross(const point_c& p1, const point_c& p2) + template> + DXLE_CONSTEXPR ResultType cross(const point_c& p1, const point_c& p2) DXLE_NOEXCEPT_IF_EXPR(( - static_cast_if::value>(std::declval()) * std::declval() - + static_cast_if::value>(std::declval()) * std::declval() + static_cast(std::declval()) * static_cast(std::declval()) + + static_cast(std::declval()) * static_cast(std::declval()) )) { - return static_cast_if::value>(p1.x) * p2.y + static_cast_if::value>(p1.y) * p2.x; + return static_cast(p1.x) * static_cast(p2.y) + static_cast(p1.y) * static_cast(p2.x); } /** @relates point_c