1 // Copyright 2009-2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #pragma once
5 
6 // stl
7 #include <algorithm>
8 // common
9 #include "constants.h"
10 #include "vec.h"
11 
12 namespace rkcommon {
13   namespace math {
14 
15     using std::max;
16     using std::min;
17 
18     /*! default implementatoin of 'anyLessThan' for scalar types, so we
19         can make a range<float>s etc. Vec-types will overwrite that and
20         test if _any_ dimension is less */
21     template <typename TA, typename TB>
anyLessThan(const TA & a,const TB & b)22     inline bool anyLessThan(const TA &a, const TB &b)
23     {
24       return a < b;
25     }
26 
27     template <typename T>
28     struct range_t
29     {
range_trange_t30       range_t() : lower(pos_inf), upper(neg_inf) {}
range_trange_t31       range_t(const EmptyTy &) : lower(pos_inf), upper(neg_inf) {}
range_trange_t32       range_t(const ZeroTy &) : lower(zero), upper(zero) {}
range_trange_t33       range_t(const OneTy &) : lower(zero), upper(one) {}
range_trange_t34       range_t(const T &t) : lower(t), upper(t) {}
range_trange_t35       range_t(const T &_lower, const T &_upper) : lower(_lower), upper(_upper)
36       {
37       }
range_trange_t38       range_t(const T *v) : lower(v[0]), upper(v[1]) {}
39 
40       template <typename other_t>
range_trange_t41       explicit range_t(const range_t<other_t> &other)
42           : lower(T(other.lower)), upper(T(other.upper))
43       {
44       }
45 
sizerange_t46       inline T size() const
47       {
48         return upper - lower;
49       }
50 
centerrange_t51       inline T center() const
52       {
53         return .5f * (lower + upper);
54       }
55 
extendrange_t56       inline void extend(const T &t)
57       {
58         lower = min(lower, t);
59         upper = max(upper, t);
60       }
61 
extendrange_t62       inline void extend(const range_t<T> &t)
63       {
64         lower = min(lower, t.lower);
65         upper = max(upper, t.upper);
66       }
67 
68       /*! take given value t, and 'clamp' it to 'this->'range; ie, if it
69           already is inside the range return as is, otherwise move it to
70           either lower or upper of this range. Warning: the value
71           returned by this can be 'upper', which is NOT strictly part of
72           the range! */
clamprange_t73       inline T clamp(const T &t) const
74       {
75         return max(lower, min(t, upper));
76       }
77 
78       /*! Try to parse given string into a range; and return if
79         successful. if not, return defaultvalue */
80       static range_t<T> fromString(
81           const std::string &string,
82           const range_t<T> &defaultValue = rkcommon::math::empty);
83 
toVec2range_t84       inline vec_t<T, 2> toVec2() const
85       {
86         return vec_t<T, 2>(lower, upper);
87       }
88 
emptyrange_t89       inline bool empty() const
90       {
91         return anyLessThan(upper, lower);
92       }
93 
containsrange_t94       inline bool contains(const T &vec) const
95       {
96         return !anyLessThan(vec, lower) && !anyLessThan(upper, vec);
97       }
98 
99       inline operator T*()
100       {
101         return static_cast<T*>(&lower);
102       }
103 
104       inline operator const T*() const
105       {
106         return static_cast<const T*>(&lower);
107       }
108 
109       T lower, upper;
110     };
111 
112     template <typename T>
113     inline std::ostream &operator<<(std::ostream &o, const range_t<T> &r)
114     {
115       o << "[" << r.lower << "," << r.upper << "]";
116       return o;
117     }
118 
119     /*! scale range, per dimension */
120     template <typename T>
121     inline range_t<T> operator*(const range_t<T> &range, const T &scale)
122     {
123       return range_t<T>(range.lower * scale, range.upper * scale);
124     }
125 
126     /*! scale range, per dimension */
127     template <typename T>
128     inline range_t<T> operator*(const T &scale, const range_t<T> &range)
129     {
130       return range_t<T>(range.lower * scale, range.upper * scale);
131     }
132 
133     /*! translate a range, per dimension */
134     template <typename T>
135     inline range_t<T> operator+(const range_t<T> &range, const T &translation)
136     {
137       return range_t<T>(range.lower + translation, range.upper + translation);
138     }
139 
140     /*! translate a range, per dimension */
141     template <typename T>
142     inline range_t<T> operator+(const T &translation, const range_t<T> &range)
143     {
144       return range_t<T>(range.lower + translation, range.upper + translation);
145     }
146 
147     // range_t aliases ////////////////////////////////////////////////////////
148 
149     using range1f = range_t<float>;
150     using range2f = range_t<vec2f>;
151     using range3f = range_t<vec3f>;
152     using range4f = range_t<vec4f>;
153     using range1i = range_t<int>;
154     using range2i = range_t<vec2i>;
155     using range3i = range_t<vec3i>;
156     using range4i = range_t<vec4i>;
157 
158   }  // namespace math
159 }  // namespace rkcommon
160