diff --git a/debug.hpp b/debug.hpp index 3bf9b617..85df0b2e 100644 --- a/debug.hpp +++ b/debug.hpp @@ -304,15 +304,23 @@ namespace debug { bool valid (const T&); - template class T, typename ...Args> + template < + template class T, + size_t S, + typename ...Args + > struct validator { - static bool is_valid (const T&); + static bool is_valid (const T&); }; - template class T, typename ...Args> - bool valid (const T &v) - { return validator::is_valid (v); } + template < + template class T, + size_t S, + typename ...Args + > + bool valid (const T &v) + { return validator::is_valid (v); } template @@ -320,7 +328,10 @@ namespace debug { { CHECK (valid (t)); } - template class T, typename ...Args> + template < + template class T, + typename ...Args + > void sanity (const T &t) { CHECK (valid (t)); } } diff --git a/extent.cpp b/extent.cpp index 810ab828..ec44ed43 100644 --- a/extent.cpp +++ b/extent.cpp @@ -25,42 +25,44 @@ #include /////////////////////////////////////////////////////////////////////////////// -template -util::extent::extent (const T _width, const T _height): +template +util::extent::extent (const T _width, const T _height): w (_width), h (_height) { + static_assert (S == 2, "extents currently only support 2 dimensions"); + CHECK_GE (w, 0); CHECK_GE (h, 0); } //----------------------------------------------------------------------------- -template -util::extent::extent (T t): +template +util::extent::extent (T t): extent (t, t) { ; } //----------------------------------------------------------------------------- -template -util::extent::extent (vector<2,T> _v): +template +util::extent::extent (vector _v): extent (_v.x, _v.y) { ; } //----------------------------------------------------------------------------- -template -util::extent::extent (const util::extent &rhs): +template +util::extent::extent (const util::extent &rhs): w (rhs.w), h (rhs.h) { ; } //----------------------------------------------------------------------------- -template -util::extent& -util::extent::operator= (const util::extent &rhs) +template +util::extent& +util::extent::operator= (extent rhs) { w = rhs.w; h = rhs.h; @@ -70,27 +72,27 @@ util::extent::operator= (const util::extent &rhs) /////////////////////////////////////////////////////////////////////////////// -template +template T -util::extent::diameter (void) const +util::extent::diameter (void) const { return static_cast (sqrt (w * w + h * h)); } //----------------------------------------------------------------------------- -template +template T -util::extent::area (void) const +util::extent::area (void) const { return w * h; } /////////////////////////////////////////////////////////////////////////////// -template -util::extent -util::extent::expanded (util::vector<2,T> mag) const +template +util::extent +util::extent::expanded (util::vector mag) const { return { w + mag.x, @@ -100,36 +102,36 @@ util::extent::expanded (util::vector<2,T> mag) const //----------------------------------------------------------------------------- -template -util::extent -util::extent::expanded (T t) const +template +util::extent +util::extent::expanded (T t) const { - return expanded (util::vector<2,T> {t}); + return expanded (util::vector {t}); } /////////////////////////////////////////////////////////////////////////////// -template +template float -util::extent::aspect (void) const +util::extent::aspect (void) const { return static_cast (w) / static_cast (h); } /////////////////////////////////////////////////////////////////////////////// -template +template bool -util::extent::empty (void) const +util::extent::empty (void) const { return almost_equal (area(), 0); } /////////////////////////////////////////////////////////////////////////////// -template +template T& -util::extent::operator[] (size_t idx) +util::extent::operator[] (size_t idx) { switch (idx) { case 0: return w; @@ -142,9 +144,9 @@ util::extent::operator[] (size_t idx) //----------------------------------------------------------------------------- -template +template const T& -util::extent::operator[] (size_t idx) const +util::extent::operator[] (size_t idx) const { switch (idx) { case 0: return w; @@ -157,18 +159,18 @@ util::extent::operator[] (size_t idx) const //----------------------------------------------------------------------------- -template +template size_t -util::extent::size (void) const +util::extent::size (void) const { - return 2u; + return S; } /////////////////////////////////////////////////////////////////////////////// -template +template bool -util::extent::operator ==(const extent& rhs) const +util::extent::operator ==(const extent& rhs) const { return almost_equal (w, rhs.w) && almost_equal (h, rhs.h); @@ -176,15 +178,15 @@ util::extent::operator ==(const extent& rhs) const /////////////////////////////////////////////////////////////////////////////// -template -const util::extent util::extent::MIN { +template +const util::extent util::extent::MIN { 0, 0 }; //----------------------------------------------------------------------------- -template -const util::extent util::extent::MAX { +template +const util::extent util::extent::MAX { std::numeric_limits::max (), std::numeric_limits::max () }; @@ -192,43 +194,43 @@ const util::extent util::extent::MAX { /////////////////////////////////////////////////////////////////////////////// namespace debug { - template - struct validator { - static bool is_valid (const util::extent &e) + template + struct validator { + static bool is_valid (const util::extent &e) { return e.w >= 0 && e.h >= 0; } }; } -template bool debug::valid (const util::extent&); -template bool debug::valid (const util::extent&); -template bool debug::valid (const util::extent&); -template bool debug::valid (const util::extent&); -template bool debug::valid (const util::extent&); +template bool debug::valid (const util::extent<2,float>&); +template bool debug::valid (const util::extent<2,double>&); +template bool debug::valid (const util::extent<2,uint16_t>&); +template bool debug::valid (const util::extent<2,uint32_t>&); +template bool debug::valid (const util::extent<2,uint64_t>&); /////////////////////////////////////////////////////////////////////////////// -template +template std::ostream& -util::operator<< (std::ostream &os, util::extent e) +util::operator<< (std::ostream &os, util::extent e) { os << "[" << e.w << ", " << e.h << "]"; return os; } -template std::ostream& util::operator<< (std::ostream&, util::extent); -template std::ostream& util::operator<< (std::ostream&, util::extent); -template std::ostream& util::operator<< (std::ostream&, util::extent); -template std::ostream& util::operator<< (std::ostream&, util::extent); -template std::ostream& util::operator<< (std::ostream&, util::extent); +template std::ostream& util::operator<< (std::ostream&, util::extent<2,uint16_t>); +template std::ostream& util::operator<< (std::ostream&, util::extent<2,uint32_t>); +template std::ostream& util::operator<< (std::ostream&, util::extent<2,uint64_t>); +template std::ostream& util::operator<< (std::ostream&, util::extent<2,float>); +template std::ostream& util::operator<< (std::ostream&, util::extent<2,double>); //----------------------------------------------------------------------------- namespace util { - template struct extent; - template struct extent; - template struct extent; - template struct extent; + template struct extent<2,uint32_t>; + template struct extent<2,uint64_t>; + template struct extent<2,float>; + template struct extent<2,double>; } diff --git a/extent.hpp b/extent.hpp index 244ebd2b..0eee6111 100644 --- a/extent.hpp +++ b/extent.hpp @@ -29,22 +29,22 @@ namespace util { /** * A pure two-dimensional size, without positioning */ - template + template struct extent { T w, h; extent (const T _width, const T _height); extent (T); - extent (vector<2,T>); + extent (vector); extent (const extent&); - extent& operator= (const extent&); + extent& operator= (extent); extent () = default; T area (void) const; T diameter (void) const; - extent expanded (util::vector<2,T>) const; - extent expanded (T) const; + extent expanded (vector) const; + extent expanded (T) const; float aspect (void) const; @@ -60,18 +60,18 @@ namespace util { { return !(*this == rhs); } template - extent cast (void) const; + extent cast (void) const; - static const extent MAX; - static const extent MIN; + static const extent MAX; + static const extent MIN; }; - typedef extent extent2i; - typedef extent extent2u; - typedef extent extent2f; + typedef extent<2,int> extent2i; + typedef extent<2,size_t> extent2u; + typedef extent<2,float> extent2f; - template - std::ostream& operator<< (std::ostream&, util::extent); + template + std::ostream& operator<< (std::ostream&, util::extent); } diff --git a/extent.ipp b/extent.ipp index ac91d88d..b01f5cd3 100644 --- a/extent.ipp +++ b/extent.ipp @@ -25,10 +25,10 @@ #define __UTIL_EXTENT_IPP //----------------------------------------------------------------------------- -template +template template -util::extent -util::extent::cast (void) const +util::extent +util::extent::cast (void) const { return { static_cast (w), diff --git a/region.cpp b/region.cpp index 3db6ce6d..a30f37c1 100644 --- a/region.cpp +++ b/region.cpp @@ -28,16 +28,16 @@ //----------------------------------------------------------------------------- -template -util::region::region (util::extent _extent): - region (util::point<2,T>::ORIGIN, _extent) +template +util::region::region (extent_t _extent): + region (point_t::ORIGIN, _extent) { ; } //----------------------------------------------------------------------------- -template -util::region::region (point<2,T> _point, - extent _size): +template +util::region::region (point_t _point, + extent_t _size): x (_point.x), y (_point.y), w (_size.w), @@ -46,9 +46,9 @@ util::region::region (point<2,T> _point, //----------------------------------------------------------------------------- -template -util::region::region (point<2,T> _a, - point<2,T> _b): +template +util::region::region (point_t _a, + point_t _b): region (_a, _b - _a) { CHECK_GE (_b.x, _a.x); @@ -56,46 +56,46 @@ util::region::region (point<2,T> _a, } //----------------------------------------------------------------------------- -template -util::region::region (position_type _x, +template +util::region::region (position_type _x, position_type _y, size_type _w, size_type _h): - region (point<2,T> {_x, _y}, extent {_w, _h}) + region (point_t {_x, _y}, extent {_w, _h}) { ; } //----------------------------------------------------------------------------- -template -typename util::region::size_type -util::region::area (void) const +template +typename util::region::size_type +util::region::area (void) const { return w * h; } //----------------------------------------------------------------------------- -template -typename util::region::size_type -util::region::diameter (void) const +template +typename util::region::size_type +util::region::diameter (void) const { return static_cast (std::sqrt (w * w + h * h)); } //----------------------------------------------------------------------------- -template -typename util::region::extent_t -util::region::magnitude (void) const +template +typename util::region::extent_t +util::region::magnitude (void) const { return { w, h }; } //----------------------------------------------------------------------------- -template -typename util::region::extent_t -util::region::magnitude (extent_t e) +template +typename util::region::extent_t +util::region::magnitude (extent_t e) { w = e.w; h = e.h; @@ -105,9 +105,9 @@ util::region::magnitude (extent_t e) //----------------------------------------------------------------------------- -template +template void -util::region::scale (T factor) +util::region::scale (T factor) { x -= (w * factor - w) / T{2}; y -= (h * factor - h) / T{2}; @@ -118,18 +118,18 @@ util::region::scale (T factor) //----------------------------------------------------------------------------- -template +template bool -util::region::empty (void) const +util::region::empty (void) const { return almost_zero (area ()); } //----------------------------------------------------------------------------- -template -util::point<2,T> -util::region::rebase (util::point<2,T> p) +template +typename util::region::point_t +util::region::rebase (point_t p) { x = p.x; y = p.y; @@ -139,39 +139,39 @@ util::region::rebase (util::point<2,T> p) //----------------------------------------------------------------------------- -template -util::point<2,T> -util::region::base (void) const +template +typename util::region::point_t +util::region::base (void) const { return { x, y }; } //----------------------------------------------------------------------------- -template -util::point<2,T> -util::region::away (void) const +template +typename util::region::point_t +util::region::away (void) const { return { x + w, y + h }; } //----------------------------------------------------------------------------- -template -util::point<2,T> -util::region::centre (void) const +template +typename util::region::point_t +util::region::centre (void) const { T cx = x + w / T{2}, cy = y + h / T{2}; - return point<2,T> { cx, cy }; + return point_t { cx, cy }; } //----------------------------------------------------------------------------- -template -util::point<2,T> -util::region::closest (point<2,T> p) const +template +typename util::region::point_t +util::region::closest (point_t p) const { return { p.x < x ? x : @@ -186,9 +186,9 @@ util::region::closest (point<2,T> p) const //----------------------------------------------------------------------------- -template +template bool -util::region::includes (const point<2,T> &p) const +util::region::includes (point_t p) const { return p.x >= x && p.y >= y && @@ -198,9 +198,9 @@ util::region::includes (const point<2,T> &p) const //----------------------------------------------------------------------------- -template +template bool -util::region::contains (const point<2,T> &p) const +util::region::contains (point_t p) const { return p.x > x && p.y > y && @@ -212,9 +212,9 @@ util::region::contains (const point<2,T> &p) const //----------------------------------------------------------------------------- // FIXME: This will fail with an actual infinite range (NaNs will be generated // in the conditionals). -template +template bool -util::region::intersects (const util::region &rhs) const +util::region::intersects (region rhs) const { return x < rhs.x + rhs.w && rhs.x < x + w && @@ -224,9 +224,9 @@ util::region::intersects (const util::region &rhs) const //----------------------------------------------------------------------------- -template +template void -util::region::constrain (point<2,T> &p) const +util::region::constrain (point_t &p) const { p.x = std::min (std::max (p.x, x), x + w); p.y = std::min (std::max (p.y, y), y + h); @@ -234,11 +234,11 @@ util::region::constrain (point<2,T> &p) const //----------------------------------------------------------------------------- -template -util::point<2,T> -util::region::constrained (const point<2,T> &p) const +template +typename util::region::point_t +util::region::constrained (point_t p) const { - point<2,T> v; + point_t v; v.x = std::min (std::max (p.x, x), x + w); v.y = std::min (std::max (p.y, y), y + h); @@ -247,9 +247,9 @@ util::region::constrained (const point<2,T> &p) const //----------------------------------------------------------------------------- -template -util::region -util::region::intersection (const util::region &rhs) const +template +util::region +util::region::intersection (region rhs) const { T newx1 = max (x, rhs.x), newy1 = max (y, rhs.y), @@ -261,14 +261,14 @@ util::region::intersection (const util::region &rhs) const size_type nw = sign_cast (newx2 - newx1); size_type nh = sign_cast (newy2 - newy1); - return util::region (newx1, newy1, nw, nh); + return util::region (newx1, newy1, nw, nh); } //----------------------------------------------------------------------------- -template -util::region -util::region::inset (T mag) +template +util::region +util::region::inset (T mag) { CHECK_GE (w, 2 * mag); CHECK_GE (h, 2 * mag); @@ -278,9 +278,9 @@ util::region::inset (T mag) //----------------------------------------------------------------------------- -template -util::region& -util::region::expand (T _w, T _h) +template +util::region& +util::region::expand (T _w, T _h) { x -= _w; y -= _h; @@ -292,18 +292,18 @@ util::region::expand (T _w, T _h) //----------------------------------------------------------------------------- -template -util::region& -util::region::expand (T mag) +template +util::region& +util::region::expand (T mag) { return expand (mag, mag); } //----------------------------------------------------------------------------- -template -util::region -util::region::expanded (T _w, T _h) const +template +util::region +util::region::expanded (T _w, T _h) const { return { x - _w, @@ -315,36 +315,36 @@ util::region::expanded (T _w, T _h) const //----------------------------------------------------------------------------- -template -util::region -util::region::expanded (T mag) const +template +util::region +util::region::expanded (T mag) const { return expanded (mag, mag); } /////////////////////////////////////////////////////////////////////////////// -template -util::region -util::region::operator+ (vector<2,T> rhs) const +template +util::region +util::region::operator+ (vector rhs) const { return { x + rhs.x, y + rhs.y, w, h }; } //----------------------------------------------------------------------------- -template -util::region -util::region::operator- (vector<2,T> rhs) const +template +util::region +util::region::operator- (vector rhs) const { return { x - rhs.x, y - rhs.y, w, h }; } /////////////////////////////////////////////////////////////////////////////// -template +template bool -util::region::operator== (const region& rhs) const +util::region::operator== (region rhs) const { return almost_equal (x, rhs.x) && almost_equal (y, rhs.y) && @@ -354,9 +354,9 @@ util::region::operator== (const region& rhs) const //----------------------------------------------------------------------------- -template +template void -util::region::sanity (void) const { +util::region::sanity (void) const { CHECK_GE (w, 0); CHECK_GE (h, 0); static_assert(!std::is_floating_point::value, @@ -367,14 +367,14 @@ util::region::sanity (void) const { //----------------------------------------------------------------------------- namespace util { template <> - void region::sanity (void) const { + void region<2,double>::sanity (void) const { CHECK_GE (w, 0); CHECK_GE (h, 0); } template <> - void region::sanity (void) const { + void region<2,float>::sanity (void) const { CHECK_GE (w, 0); CHECK_GE (h, 0); } @@ -389,9 +389,9 @@ namespace util { /// /// Specifically does not allow infinities. Use/define INFINITE when required. -template -const util::region -util::region::MAX ( +template +const util::region +util::region::MAX ( std::numeric_limits::lowest () / 2, std::numeric_limits::lowest () / 2, std::numeric_limits::max (), @@ -399,15 +399,15 @@ util::region::MAX ( ); -template -const util::region -util::region::UNIT (0, 0, 1, 1); +template +const util::region +util::region::UNIT (0, 0, 1, 1); //----------------------------------------------------------------------------- -template +template std::ostream& -util::operator<< (std::ostream &os, const util::region &rhs) { +util::operator<< (std::ostream &os, const util::region &rhs) { os << "region(" << rhs.x << ", " << rhs.y << ", " << rhs.w << ", " << rhs.h << ")"; return os; } @@ -415,15 +415,15 @@ util::operator<< (std::ostream &os, const util::region &rhs) { //----------------------------------------------------------------------------- namespace util { - template struct region; - template struct region; - template struct region; - template struct region; + template struct region<2,uint32_t>; + template struct region<2,uint64_t>; + template struct region<2,float>; + template struct region<2,double>; - template std::ostream& operator<< (std::ostream&, const region< int32_t>&); - template std::ostream& operator<< (std::ostream&, const region< int64_t>&); - template std::ostream& operator<< (std::ostream&, const region&); - template std::ostream& operator<< (std::ostream&, const region&); - template std::ostream& operator<< (std::ostream&, const region< float>&); - template std::ostream& operator<< (std::ostream&, const region< double>&); + template std::ostream& operator<< (std::ostream&, const region<2, int32_t>&); + template std::ostream& operator<< (std::ostream&, const region<2, int64_t>&); + template std::ostream& operator<< (std::ostream&, const region<2,uint32_t>&); + template std::ostream& operator<< (std::ostream&, const region<2,uint64_t>&); + template std::ostream& operator<< (std::ostream&, const region<2, float>&); + template std::ostream& operator<< (std::ostream&, const region<2, double>&); } diff --git a/region.hpp b/region.hpp index 125ac2de..840ebdc8 100644 --- a/region.hpp +++ b/region.hpp @@ -30,25 +30,25 @@ namespace util { /** * A two-dimensional rectangle, with size and position. */ - template + template struct region { using position_type = T; using size_type = typename try_unsigned::type; - static constexpr size_t dimension = 2u; + static constexpr size_t dimension = S; static constexpr size_t elements = dimension * 2; using value_type = T; - using extent_t = util::extent; - using point_t = util::point<2,T>; + using extent_t = util::extent; + using point_t = util::point; position_type x, y; size_type w, h; region () = default; - region (util::extent); - region (util::point<2,T>, util::extent); - region (util::point<2,T>, util::point<2,T>); + region (extent_t); + region (point_t, extent_t); + region (point_t, point_t); region (T _x, T _y, size_type _w, size_type _h); size_type area (void) const; @@ -60,24 +60,24 @@ namespace util { bool empty (void) const; - point<2,T> rebase (util::point<2,T>); + point_t rebase (point_t); - point<2,T> base (void) const; - point<2,T> away (void) const; - point<2,T> centre (void) const; - point<2,T> closest (point<2,T>) const; + point_t base (void) const; + point_t away (void) const; + point_t centre (void) const; + point_t closest (point_t) const; // Point and region relation queries - bool includes (const point<2,T>&) const; // inclusive of borders - bool contains (const point<2,T>&) const; // exclusive of borders - bool intersects (const region&) const; // exclusive of borders + bool includes (point_t) const; // inclusive of borders + bool contains (point_t) const; // exclusive of borders + bool intersects (region) const; // exclusive of borders // Move a point to be within the region bounds - void constrain (point<2,T>&) const; - point<2,T> constrained (const point<2,T>&) const; + void constrain (point_t&) const; + point_t constrained (point_t) const; // Compute binary region combinations - region intersection (const region&) const; + region intersection (region) const; // Compute a region `mag` units into the region region inset (T mag); @@ -89,27 +89,28 @@ namespace util { region& expand (T w, T h); // arithmetic operators - region operator+ (vector<2,T>) const; - region operator- (vector<2,T>) const; + region operator+ (vector) const; + region operator- (vector) const; // Logical comparison operators - bool operator ==(const region& rhs) const; - bool operator !=(const region& rhs) const + bool operator ==(region rhs) const; + bool operator !=(region rhs) const { return !(*this == rhs); } // Utility constants - static const region MAX; - static const region UNIT; + static const region MAX; + static const region UNIT; void sanity (void) const; }; - typedef region region2u; - typedef region region2i; - typedef region region2f; + typedef region<2,size_t> region2u; + typedef region<2,intmax_t> region2i; + typedef region<2,float> region2f; + typedef region<2,double> region2d; - template - std::ostream& operator<< (std::ostream&, const util::region&); + template + std::ostream& operator<< (std::ostream&, const util::region&); } diff --git a/test/extent.cpp b/test/extent.cpp index 40ee0f56..def7f591 100644 --- a/test/extent.cpp +++ b/test/extent.cpp @@ -4,5 +4,6 @@ int main (void) { - debug::sanity (util::extent {0, 0}); + // Simple symbol visibility check + util::extent2f instance; } diff --git a/test/region.cpp b/test/region.cpp index 7c86a490..d0b3aa5a 100644 --- a/test/region.cpp +++ b/test/region.cpp @@ -2,35 +2,33 @@ #include "../point.hpp" #include "../debug.hpp" -using util::region; -using util::point; -using util::point2d; +using namespace util; int main (int, char **) { { - region a (32.7, -6.09703, 0.8, 2); - region b (33.5, -4.5, 0.5, 0.5); + region2d a {32.7, -6.09703, 0.8, 2}; + region2d b {33.5, -4.5, 0.5, 0.5}; CHECK (!a.intersects (b)); } - CHECK (region::MAX.intersects (region::UNIT)); - CHECK (region< float>::MAX.intersects (region< float>::UNIT)); + CHECK (region2d::MAX.intersects (region2d::UNIT)); + CHECK (region2f::MAX.intersects (region2f::UNIT)); - CHECK_EQ (region::UNIT.area (), 1.0); - CHECK_EQ (region< float>::UNIT.area (), 1.0f); + CHECK_EQ (region2d::UNIT.area (), 1.0); + CHECK_EQ (region2f::UNIT.area (), 1.0f); - CHECK (region (0, 0, 2, 2).includes (point<2,unsigned>(1, 1))); - CHECK (region (0, 0, 2, 2).includes (point<2,unsigned>(0, 0))); - CHECK (region (0, 0, 2, 2).includes (point<2,unsigned>(2, 2))); + CHECK (region2u (0, 0, 2, 2).includes (point2u {1, 1})); + CHECK (region2u (0, 0, 2, 2).includes (point2u {0, 0})); + CHECK (region2u (0, 0, 2, 2).includes (point2u {2, 2})); - CHECK ( region (0, 0, 2, 2).contains (point<2,unsigned>(1, 1))); - CHECK (!region (0, 0, 2, 2).contains (point<2,unsigned>(0, 0))); - CHECK (!region (0, 0, 2, 2).contains (point<2,unsigned>(2, 2))); + CHECK ( region2u (0, 0, 2, 2).contains (point2u {1, 1})); + CHECK (!region2u (0, 0, 2, 2).contains (point2u {0, 0})); + CHECK (!region2u (0, 0, 2, 2).contains (point2u {2, 2})); - //CHECK (region (0, 0, 10, 10).includes (point2d (0.4, 0.01))); - //CHECK (region (0, 0, 10, 10).contains (point2d (0.4, 0.01))); + //CHECK (region<2,intmax_t> (0, 0, 10, 10).includes (point2d (0.4, 0.01))); + //CHECK (region<2,intmax_t> (0, 0, 10, 10).contains (point2d (0.4, 0.01))); return 0; }