1 /* This file is part of Dilay
2  * Copyright © 2015-2018 Alexander Bau
3  * Use and redistribute under the terms of the GNU General Public License
4  */
5 #ifndef DILAY_UTIL
6 #define DILAY_UTIL
7 
8 #include <algorithm>
9 #include <functional>
10 #include <glm/fwd.hpp>
11 #include <limits>
12 #include <locale>
13 #include <vector>
14 #include "log.hpp"
15 
16 #define DILAY_INFO(fmt, ...) Log::log (Log::Level::Info, __FILE__, __LINE__, fmt, ##__VA_ARGS__);
17 #define DILAY_WARN(fmt, ...) Log::log (Log::Level::Warning, __FILE__, __LINE__, fmt, ##__VA_ARGS__);
18 #define DILAY_PANIC(fmt, ...)                                                              \
19   {                                                                                        \
20     Log::log (Log::Level::Panic, __FILE__, __LINE__, fmt, ##__VA_ARGS__);                  \
21     Log::log (Log::Level::Panic, __FILE__, __LINE__, "aborting due to previous error..."); \
22     std::abort ();                                                                         \
23   }
24 #define DILAY_IMPOSSIBLE DILAY_PANIC ("the impossible happend")
25 
26 #define unused(x) ((void) (x))
27 
28 typedef std::pair<unsigned int, unsigned int> ui_pair;
29 
30 namespace Util
31 {
32   glm::vec3    midpoint (const glm::vec3&, const glm::vec3&);
33   glm::vec3    transformPosition (const glm::mat4x4&, const glm::vec3&);
34   glm::vec3    transformDirection (const glm::mat4x4&, const glm::vec3&);
35   glm::vec3    orthogonal (const glm::vec3&);
36   glm::ivec2   orthogonalRight (const glm::ivec2&);
37   glm::mat4x4  rotation (const glm::vec3&, const glm::vec3&, float);
38   bool         colinear (const glm::vec2&, const glm::vec2&);
39   bool         colinear (const glm::vec3&, const glm::vec3&);
40   bool         colinearUnit (const glm::vec2&, const glm::vec2&);
41   bool         colinearUnit (const glm::vec3&, const glm::vec3&);
42   float        smoothStep (const glm::vec3&, const glm::vec3&, float, float);
43   float        linearStep (const glm::vec3&, const glm::vec3&, float, float);
44   float        cross (const glm::vec2&, const glm::vec2&);
45   std::string  readFile (const std::string&);
46   unsigned int solveQuadraticEq (float, float, float, float&, float&);
47   unsigned int solveCubicEq (float, float, float, float&, float&, float&);
48   unsigned int solveCubicEq (float, float, float, float, float&, float&, float&);
49   bool         isNaN (float);
50   bool         isNaN (const glm::vec3&);
51   bool         isNotNull (const glm::vec3&);
52   bool         almostEqual (float, float);
53   void         warn (const char*, unsigned int, const char*, ...);
54   bool         fromString (const std::string&, int&);
55   bool         fromString (const std::string&, unsigned int&);
56   bool         fromString (const std::string&, float&);
57   unsigned int countOnes (unsigned int);
58   bool         hasSuffix (const std::string&, const std::string&);
59 
epsilon()60   constexpr float epsilon () { return 0.0001f; }
61 
minFloat()62   constexpr float minFloat () { return std::numeric_limits<float>::lowest (); }
63 
maxFloat()64   constexpr float maxFloat () { return std::numeric_limits<float>::max (); }
65 
minInt()66   constexpr int minInt () { return std::numeric_limits<int>::lowest (); }
67 
maxInt()68   constexpr int maxInt () { return std::numeric_limits<int>::max (); }
69 
maxUnsignedInt()70   constexpr int maxUnsignedInt () { return std::numeric_limits<unsigned int>::max (); }
71 
invalidIndex()72   constexpr unsigned int invalidIndex () { return std::numeric_limits<unsigned int>::max (); }
73 
setIfNotNull(T * ptr,const T & value)74   template <typename T> void setIfNotNull (T* ptr, const T& value)
75   {
76     if (ptr)
77     {
78       *ptr = value;
79     }
80   }
81 
findIndexByReference(const std::vector<T> & vec,const T & obj)82   template <typename T> unsigned int findIndexByReference (const std::vector<T>& vec, const T& obj)
83   {
84     return &obj - &vec.at (0);
85   }
86 
withCLocale(const std::function<T ()> & f)87   template <typename T> T withCLocale (const std::function<T ()>& f)
88   {
89     const std::locale prev = std::locale::global (std::locale::classic ());
90     T                 result = f ();
91     std::locale::global (prev);
92     return result;
93   }
94   template <> void withCLocale (const std::function<void()>& f);
95 
96   template <typename T>
prune(std::vector<T> & v,const std::function<bool (const T &)> & p,std::vector<unsigned int> * indexMap=nullptr)97   void prune (std::vector<T>& v, const std::function<bool(const T&)>& p,
98               std::vector<unsigned int>* indexMap = nullptr)
99   {
100     if (indexMap)
101     {
102       indexMap->resize (v.size (), Util::invalidIndex ());
103     }
104     auto lastIt = std::find_if_not (v.rbegin (), v.rend (), p);
105 
106     if (lastIt == v.rend ())
107     {
108       v.clear ();
109     }
110     else
111     {
112       unsigned int last = v.size () - (lastIt - v.rbegin ()) - 1;
113 
114       for (unsigned int i = 0; i <= last; i++)
115       {
116         if (p (v[i]))
117         {
118           v[i] = v[last];
119 
120           if (indexMap)
121           {
122             (*indexMap)[i] = Util::invalidIndex ();
123             (*indexMap)[last] = i;
124           }
125 
126           do
127           {
128             last--;
129           } while (p (v[last]));
130         }
131         else
132         {
133           if (indexMap)
134           {
135             (*indexMap)[i] = i;
136           }
137         }
138       }
139       v.resize (last + 1);
140     }
141   }
142 }
143 
144 #endif
145