Coverity: ast module uninitialized members fixed
[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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 #ifndef __FORLIST_HXX__
17 #define __FORLIST_HXX__
18
19 #include <iostream>
20 #include <type_traits>
21
22 #include "tools.hxx"
23 #include "TIType.hxx"
24 #include "core_math.h"
25
26 namespace analysis
27 {
28 template<typename T>
29 class ForList
30 {
31     bool constant;
32     bool read_in_loop;
33     double min;
34     double step;
35     double max;
36     bool _int;
37     bool _unsigned;
38
39     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");
40
41 public:
42
43     ForList() : constant(false), read_in_loop(false), min(0), step(0), max(0), _int(false), _unsigned(false) { }
44
45     ForList(const double m, const double s, const double M) : constant(true), read_in_loop(false), min(m), step(s), max(M)
46     {
47         if (!isempty())
48         {
49             if (min >= 0 && step > 0 && is_int<typename std::make_unsigned<T>::type>(min) && is_int<typename std::make_unsigned<T>::type>(step) && !overflow<typename std::make_unsigned<T>::type>(min, step, max))
50             {
51                 _int = true;
52                 _unsigned = true;
53             }
54             else if (is_int<typename std::make_signed<T>::type>(min) && is_int<typename std::make_signed<T>::type>(step) && !overflow<typename std::make_signed<T>::type>(min, step, max))
55             {
56                 _int = true;
57                 _unsigned = false;
58             }
59             else
60             {
61                 _int = false;
62                 _unsigned = false;
63             }
64         }
65         else
66         {
67             _int = false;
68             _unsigned = false;
69         }
70     }
71
72     inline bool is_read_in_loop() const
73     {
74         return read_in_loop;
75     }
76
77     inline void set_read_in_loop(const bool read)
78     {
79         read_in_loop = read;
80     }
81
82     inline bool is_constant() const
83     {
84         return constant;
85     }
86
87     inline bool is_int() const
88     {
89         return _int;
90     }
91
92     inline bool is_uint() const
93     {
94         return _unsigned;
95     }
96
97     template<typename U>
98     inline U get_min() const
99     {
100         return std::is_integral<U>::value ? tools::trunc(min) : min;
101     }
102
103     template<typename U>
104     inline U get_step() const
105     {
106         return std::is_integral<U>::value ? tools::trunc(step) : step;
107     }
108
109     template<typename U>
110     inline U get_max() const
111     {
112         return std::is_integral<U>::value ? tools::trunc(max) : max;
113     }
114
115     friend std::wostream & operator<<(std::wostream & out, const ForList & fl)
116     {
117         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");
118         return out;
119     }
120
121     inline static bool isempty(const double min, const double max, const double step)
122     {
123         return step == 0 || tools::isNaN(min) || tools::isNaN(step) || tools::isNaN(max) || !tools::isFinite(min) || !tools::isFinite(step) || !tools::isFinite(max) || (min < max && step < 0) || (min > max && step > 0);
124     }
125
126     inline static uint64_t size(const double min, const double max, const double step)
127     {
128         return (uint64_t)std::floor((max - min) / step) + 1;
129     }
130
131     inline static int checkList(const double min, const double max, const double step, double & out)
132     {
133         if (step == 0)
134         {
135             if (tools::isNaN(min) || tools::isNaN(max))
136             {
137                 out = tools::NaN();
138                 return 1; // one value
139             }
140             else
141             {
142                 return 0; // empty
143             }
144         }
145         else
146         {
147             if (tools::isNaN(min) || tools::isNaN(step) || tools::isNaN(max))
148             {
149                 out = tools::NaN();
150                 return 1; // one value
151             }
152             else
153             {
154                 if (min < max)
155                 {
156                     if (step < 0)
157                     {
158                         return 0; //empty
159                     }
160                 }
161                 else if (step > 0)
162                 {
163                     return 0; // empty
164                 }
165
166                 if (!tools::isFinite(min) || !tools::isFinite(max))
167                 {
168                     out = tools::NaN();
169                     return 1; // one value
170                 }
171                 else
172                 {
173                     return 2; //one or more...
174                 }
175             }
176         }
177     }
178
179 private:
180
181     inline bool isempty() const
182     {
183         return isempty(min, max, step);
184     }
185
186     template<typename U>
187     inline static bool is_int(const double x)
188     {
189         const U y = (U)tools::trunc(x);
190         return x == y && y <= std::numeric_limits<U>::max() && y >= std::numeric_limits<U>::min();
191     }
192
193     template<typename U>
194     inline static U to_int(const double x)
195     {
196         return tools::trunc(x);
197     }
198
199     template<typename U>
200     inline static bool overflow(const double m, const double s, const double M)
201     {
202         if (s > 0)
203         {
204             // m + k.s <= MAX<U> < m + (k + 1).s
205             const double k = std::floor(((double)std::numeric_limits<U>::max() - m) / s);
206
207             // so if m + k * s < M then m + (k + 1).s > MAX<U> => overflow
208             return m + k * s < M;
209         }
210         else
211         {
212             // m + k.s >= MIN<U> > m + (k + 1).s
213             const double k = std::floor(((double)std::numeric_limits<U>::min() - m) / s);
214
215             // so if m + k * s > M then m + (k + 1).s < MIN<U> => overflow
216             return m + k * s > M;
217         }
218     }
219 };
220
221 typedef ForList<int64_t> ForList64;
222 typedef ForList<int32_t> ForList32;
223
224 } // namespace analysis
225
226 #endif // __FORLIST_HXX__