829f9a3a66541e466139998df5b92a9369dbb8ea
[platform/upstream/dldt.git] / inference-engine / src / vpu / graph_transformer / include / vpu / utils / checked_cast.hpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #pragma once
6
7 #ifdef __INTEL_COMPILER
8 #pragma warning disable: 54
9 #endif
10
11 #include <type_traits>
12 #include <limits>
13
14 #include <details/ie_exception.hpp>
15
16 namespace vpu {
17
18 namespace details {
19
20 template <bool Cond, class Func>
21 inline typename std::enable_if<Cond, void>::type runIf(Func&& func) {
22     func();
23 }
24 template <bool Cond, class Func>
25 inline typename std::enable_if<!Cond, void>::type runIf(Func&&) {
26 }
27
28 // To overcame syntax parse error, when `>` comparison operator is threated as template closing bracket
29 template <typename T1, typename T2>
30 constexpr inline bool Greater(T1&& v1, T2&& v2) {
31     return v1 > v2;
32 }
33
34 }  // namespace details
35
36 template <typename OutT, typename InT>
37 inline typename std::enable_if<
38         std::is_same<OutT, InT>::value,
39 OutT>::type checked_cast(InT value) {
40     return value;
41 }
42
43 template <typename OutT, typename InT>
44 inline typename std::enable_if<
45         std::is_integral<OutT>::value && std::is_integral<InT>::value &&
46         std::is_signed<OutT>::value && std::is_signed<InT>::value &&
47         !std::is_same<OutT, InT>::value,
48 OutT>::type checked_cast(InT value) {
49     details::runIf<
50         std::numeric_limits<InT>::lowest() < std::numeric_limits<OutT>::lowest()
51     >([&] {
52         IE_ASSERT(value >= std::numeric_limits<OutT>::lowest()) << value;
53     });
54     details::runIf<
55         details::Greater(std::numeric_limits<InT>::max(), std::numeric_limits<OutT>::max())
56     >([&] {
57         IE_ASSERT(value <= std::numeric_limits<OutT>::max()) << value;
58     });
59
60     return static_cast<OutT>(value);
61 }
62
63 template <typename OutT, typename InT>
64 typename std::enable_if<
65         std::is_integral<OutT>::value && std::is_integral<InT>::value &&
66         std::is_unsigned<OutT>::value && std::is_unsigned<InT>::value &&
67         !std::is_same<OutT, InT>::value,
68     OutT>::type checked_cast(InT value) {
69     details::runIf<
70         details::Greater(std::numeric_limits<InT>::max(), std::numeric_limits<OutT>::max())
71     >([&] {
72         IE_ASSERT(value <= std::numeric_limits<OutT>::max()) << value;
73     });
74
75     return static_cast<OutT>(value);
76 }
77
78 template <typename OutT, typename InT>
79 typename std::enable_if<
80         std::is_integral<OutT>::value && std::is_integral<InT>::value &&
81         std::is_signed<OutT>::value && std::is_unsigned<InT>::value,
82     OutT>::type checked_cast(InT value) {
83     details::runIf<
84         details::Greater(std::numeric_limits<InT>::max(), static_cast<typename std::make_unsigned<OutT>::type>(std::numeric_limits<OutT>::max()))
85     >([&] {
86         IE_ASSERT(value <= static_cast<typename std::make_unsigned<OutT>::type>(std::numeric_limits<OutT>::max())) << value;
87     });
88
89     return static_cast<OutT>(value);
90 }
91
92 template <typename OutT, typename InT>
93 typename std::enable_if<
94         std::is_integral<OutT>::value && std::is_integral<InT>::value &&
95         std::is_unsigned<OutT>::value && std::is_signed<InT>::value,
96     OutT>::type checked_cast(InT value) {
97     IE_ASSERT(value >= 0) << value;
98     details::runIf<
99         details::Greater(static_cast<typename std::make_unsigned<InT>::type>(std::numeric_limits<InT>::max()), std::numeric_limits<OutT>::max())
100     >([&] {
101         IE_ASSERT(static_cast<typename std::make_unsigned<InT>::type>(value) <= std::numeric_limits<OutT>::max()) << value;
102     });
103
104     return static_cast<OutT>(value);
105 }
106
107 template <typename OutT, typename InT>
108 typename std::enable_if<
109         std::is_integral<OutT>::value && std::is_floating_point<InT>::value,
110     OutT>::type checked_cast(InT value) {
111     IE_ASSERT(value <= static_cast<InT>(std::numeric_limits<OutT>::max())) << value;
112     IE_ASSERT(value >= static_cast<InT>(std::numeric_limits<OutT>::lowest())) << value;
113
114     return static_cast<OutT>(value);
115 }
116
117 template <typename OutT, typename InT>
118 typename std::enable_if<
119         std::is_same<float, OutT>::value && std::is_same<double, InT>::value,
120     OutT>::type checked_cast(InT value) {
121     IE_ASSERT(static_cast<double>(static_cast<float>(value)) == value) << value;
122
123     return static_cast<OutT>(value);
124 }
125
126 }  // namespace vpu