fix library path
[scilab.git] / scilab / modules / ast / includes / analysis / ForList.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014 - Scilab Enterprises - Calixte DENIZET
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #ifndef __FORLIST_HXX__
14 #define __FORLIST_HXX__
15
16 #include <iostream>
17 #include <type_traits>
18
19 #include "TIType.hxx"
20 #include "core_math.h"
21
22 #ifdef _MSC_VER
23 #include "stdint.h"
24 #define TRUNC(x) ((x) > 0 ? floor(x) : ceil(x))
25 #else
26 #ifdef __APPLE__
27 #define TRUNC(x) ((x) > 0 ? floor(x) : ceil(x))
28 #else
29 #define TRUNC(x) (std::trunc(x))
30 #endif
31 #endif
32
33 namespace analysis
34 {
35 template<typename T>
36 class ForList
37 {
38     bool constant;
39     bool read_in_loop;
40     double min;
41     double step;
42     double max;
43     bool _int;
44     bool _unsigned;
45
46     static_assert(std::is_same<typename std::make_signed<T>::type, int32_t>::value || std::is_same<typename std::make_signed<T>::type, int64_t>::value, "ForList template parameter must be int32_t or int64_t");
47
48 public:
49
50     ForList() : constant(false), read_in_loop(false) { }
51
52     ForList(const double m, const double s, const double M) : constant(true), read_in_loop(false), min(m), step(s), max(M)
53     {
54         if (!isEmpty())
55         {
56             if (min >= 0 && step > 0 && isInt<typename std::make_unsigned<T>::type>(min) && isInt<typename std::make_unsigned<T>::type>(step) && !overflow<typename std::make_unsigned<T>::type>(min, step, max))
57             {
58                 _int = true;
59                 _unsigned = true;
60             }
61             else if (isInt<typename std::make_signed<T>::type>(min) && isInt<typename std::make_signed<T>::type>(step) && !overflow<typename std::make_signed<T>::type>(min, step, max))
62             {
63                 _int = true;
64                 _unsigned = false;
65             }
66             else
67             {
68                 _int = false;
69                 _unsigned = false;
70             }
71         }
72         else
73         {
74             _int = false;
75             _unsigned = false;
76         }
77     }
78
79     inline bool isReadInLoop() const
80     {
81         return read_in_loop;
82     }
83
84     inline void setReadInLoop(const bool read)
85     {
86         read_in_loop = read;
87     }
88
89     inline bool isConstant() const
90     {
91         return constant;
92     }
93
94     inline bool isInt() const
95     {
96         return _int;
97     }
98
99     inline bool isUInt() const
100     {
101         return _unsigned;
102     }
103
104     template<typename U>
105     inline U getMin() const
106     {
107         return std::is_integral<U>::value ? TRUNC(min) : min;
108     }
109
110     template<typename U>
111     inline U getStep() const
112     {
113         return std::is_integral<U>::value ? TRUNC(step) : step;
114     }
115
116     template<typename U>
117     inline U getMax() const
118     {
119         return std::is_integral<U>::value ? TRUNC(max) : max;
120     }
121
122     inline TIType getType() const
123     {
124         /*
125             if (isempty())
126             {
127                 return TIType(TIType::EMPTY);
128             }
129
130             if (is_int())
131             {
132                 if (is_uint())
133                 {
134                     if (std::is_same<T, int32_t>::value)
135                     {
136                         return TIType(TIType::UINT32);
137                     }
138                     else
139                     {
140                         return TIType(TIType::UINT64);
141                     }
142                 }
143                 else
144                 {
145                     if (std::is_same<T, int64_t>::value)
146                     {
147                         return TIType(TIType::INT32);
148                     }
149                     else
150                     {
151                         return TIType(TIType::INT64);
152                     }
153                 }
154             }
155         */
156
157         return TIType(TIType::DOUBLE);
158     }
159
160     friend std::wostream & operator<<(std::wostream & out, const ForList & fl)
161     {
162         out << L"ForList: { m: " << fl.min << L", s: " << fl.step << L", M: " << fl.max << L", int: " << (fl._int ? L"T" : L"F") << L", uint: " << (fl._unsigned ? L"T" : L"F");
163         return out;
164     }
165
166 private:
167
168     inline bool isEmpty() const
169     {
170         return step == 0 || ISNAN(min) || ISNAN(step) || ISNAN(max) || !finite(min) || !finite(step) || !finite(max) || (min < max && step < 0) || (min > max && step > 0);
171     }
172
173     template<typename U>
174     inline static bool isInt(const double x)
175     {
176         return x == TRUNC(x) && x <= std::numeric_limits<U>::max() && x >= std::numeric_limits<U>::min();
177     }
178
179     template<typename U>
180     inline static U toInt(const double x)
181     {
182         return TRUNC(x);
183     }
184
185     template<typename U>
186     inline static bool overflow(const double m, const double s, const double M)
187     {
188         if (s > 0)
189         {
190             // m + k.s <= MAX<U> < m + (k + 1).s
191             const double k = std::floor(((double)std::numeric_limits<U>::max() - m) / s);
192
193             // so if m + k * s < M then m + (k + 1).s > MAX<U> => overflow
194             return m + k * s < M;
195         }
196         else
197         {
198             // m + k.s >= MIN<U> > m + (k + 1).s
199             const double k = std::floor(((double)std::numeric_limits<U>::min() - m) / s);
200
201             // so if m + k * s > M then m + (k + 1).s < MIN<U> => overflow
202             return m + k * s > M;
203         }
204     }
205 };
206
207 typedef ForList<int64_t> ForList64;
208 typedef ForList<int32_t> ForList32;
209
210 } // namespace analysis
211
212 #endif // __FORLIST_HXX__