1 #ifndef _melder_int_h_
2 #define _melder_int_h_
3 /* melder_int.h
4 *
5 * Copyright (C) 1992-2020 Paul Boersma
6 *
7 * This code is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
11 *
12 * This code is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this work. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 /*
22 The following two lines are for obsolete (i.e. C99) versions of stdint.h
23 */
24 #define __STDC_LIMIT_MACROS
25 #define __STDC_CONSTANT_MACROS
26 #include <stdint.h>
27 using byte = unsigned char;
28 using int8 = int8_t;
29 using int16 = int16_t;
30 using int32 = int32_t;
31 using int64 = int64_t;
32 using integer = intptr_t; // the default size of an integer (a "long" is only 32 bits on 64-bit Windows)
33 using long_not_integer = long; // for cases where we explicitly need the type "long", such as when printfing to %ld
34 using int_not_integer = int; // for cases where we explicitly need the type "int", such as when scanfing to %n
35 using uinteger = uintptr_t;
36 using uint8 = uint8_t;
37 using uint16 = uint16_t;
38 using uint32 = uint32_t;
39 using uint64 = uint64_t;
40 #ifndef INT12_MAX
41 #define INT12_MAX 2047
42 #define INT12_MIN -2048
43 #endif
44 #ifndef UINT12_MAX
45 #define UINT12_MAX 4096
46 #endif
47 #ifndef INT24_MAX
48 #define INT24_MAX 8388607
49 #define INT24_MIN -8388608
50 #endif
51 #ifndef UINT24_MAX
52 #define UINT24_MAX 16777216
53 #endif
54 #define INTEGER_MAX ( sizeof (integer) == 4 ? INT32_MAX : INT64_MAX )
55 #define INTEGER_MIN ( sizeof (integer) == 4 ? INT32_MIN : INT64_MIN )
56 /*
57 The bounds of the contiguous set of integers that in a "double" can represent only themselves.
58 */
59 #ifndef INT54_MAX
60 #define INT54_MAX 9007199254740991LL
61 #define INT54_MIN -9007199254740991LL
62 #endif
63
Melder_integersAreBigEndian()64 inline bool Melder_integersAreBigEndian () {
65 int32_t dummy = 1;
66 return * (char *) & dummy == '\0';
67 }
68
69 inline integer operator"" _integer (unsigned long long value) { return integer (value); }
70
71 /*
72 We assume that the types "integer" and "uinteger" are both large enough to contain
73 any possible value that Praat wants to assign to them.
74 This entails that we assume that these types can be converted to each other without bounds checking.
75 We therefore crash Praat if this second assumption is not met.
76 */
integer_to_uinteger(integer n)77 inline uinteger integer_to_uinteger (integer n) {
78 Melder_assert (n >= 0);
79 return (uinteger) n;
80 }
uinteger_to_integer(uinteger n)81 inline integer uinteger_to_integer (uinteger n) {
82 Melder_assert (n <= INTEGER_MAX);
83 return (integer) n;
84 }
integer_to_int32(integer n)85 inline int32 integer_to_int32 (integer n) {
86 Melder_assert (n >= INT32_MIN && n <= INT32_MAX);
87 return (int32) n;
88 }
Melder_iroundUpToPowerOfTwo(integer n)89 inline integer Melder_iroundUpToPowerOfTwo (integer n) {
90 if (n <= 0)
91 return 1;
92 if (n > INTEGER_MAX / 2 + 1)
93 return 0; // 0 signals overflow; note that signed integer overflow is UB in C++, so this test cannot be removed by relying on n becoming negative
94 n -= 1;
95 n |= n >> 1; // copy the highest 1-bit to its right
96 n |= n >> 2; // copy the two highest 1-bits to their right
97 n |= n >> 4; // copy the four highest 1-bits to their right
98 n |= n >> 8; // copy the eight highest 1-bits to their right
99 n |= n >> 16; // copy the 16 highest 1-bits to their right
100 if (sizeof (integer) > 4)
101 n |= (n >> 16) >> 16; // copy the 32 highest 1-bits to their right ("n >> 32" would give a compiler warning on 32-bit platforms)
102 n += 1;
103 return n;
104 }
105
integer_abs(integer n)106 inline integer integer_abs (integer n) {
107 Melder_assert (sizeof (integer) == sizeof (long) || sizeof (integer) == sizeof (long long));
108 if (sizeof (integer) == sizeof (long))
109 return labs (n);
110 else // sizeof (integer) == sizeof (long long)
111 return llabs (n);
112 }
113
114 struct MelderIntegerRange {
115 integer first, last;
isEmptyMelderIntegerRange116 bool isEmpty () { return ( last < first ); }
sizeMelderIntegerRange117 integer size () const {
118 integer result = last - first + 1;
119 return std::max (result, 0_integer);
120 }
121 };
122
123 template <typename T>
Melder_clipLeft(T minimum,T * var)124 void Melder_clipLeft (T minimum, T *var) { // no action if either undefined
125 if (*var < minimum)
126 *var = minimum;
127 }
128
129 template <typename T>
Melder_clippedLeft(T minimum,T var)130 T Melder_clippedLeft (T minimum, T var) {
131 return var < minimum ? minimum : var; // if minimum undefined, then var
132 }
133
134 template <typename T>
Melder_clipRight(T * var,T maximum)135 void Melder_clipRight (T *var, T maximum) { // no action if either undefined
136 if (*var > maximum)
137 *var = maximum;
138 }
139
140 template <typename T>
Melder_clippedRight(T var,T maximum)141 T Melder_clippedRight (T var, T maximum) {
142 return var > maximum ? maximum : var; // if maximum undefined, then var
143 }
144
145 template <typename T>
Melder_clip(T minimum,T * var,T maximum)146 void Melder_clip (T minimum, T *var, T maximum) {
147 Melder_assert (! (maximum < minimum)); // NaN-safe
148 if (*var < minimum)
149 *var = minimum;
150 else if (*var > maximum)
151 *var = maximum;
152 }
153
154 template <typename T>
Melder_clipped(T minimum,T var,T maximum)155 T Melder_clipped (T minimum, T var, T maximum) {
156 Melder_assert (! (maximum < minimum)); // NaN-safe
157 return var < minimum ? minimum : var > maximum ? maximum : var; // if minimum and maximum undefined, then var
158 }
159
160 template <typename T>
Melder_moveCloserToBy(T * x,T to,T by)161 void Melder_moveCloserToBy (T *x, T to, T by) {
162 if (*x < to)
163 *x = Melder_clippedRight (*x + by, to);
164 else if (*x > to)
165 *x = Melder_clippedLeft (to, *x - by);
166 }
167
168 template <typename T>
Melder_sort(T * p1,T * p2)169 void Melder_sort (T *p1, T *p2) {
170 if (*p2 < *p1)
171 std::swap (*p1, *p2);
172 }
173
174 class kleenean {
175 int _intValue;
176 public:
177 constexpr static int UNKNOWN = -1;
178 constexpr static int NO_ = 0;
179 constexpr static int YES_ = 1;
kleenean(int initialValue)180 explicit constexpr kleenean (int initialValue): _intValue (initialValue) { }
isTrue()181 bool isTrue () const noexcept {
182 return our _intValue > 0;
183 }
isFalse()184 bool isFalse () const noexcept {
185 return our _intValue == 0;
186 }
isUnknown()187 bool isUnknown () const noexcept {
188 return our _intValue < 0;
189 }
isKnown()190 bool isKnown () const noexcept {
191 return our _intValue >= 0;
192 }
193 explicit operator bool () const noexcept {
194 return our isTrue();
195 }
196 bool operator! () const noexcept {
197 return our isFalse();
198 }
199 kleenean operator&& (const kleenean other) const noexcept {
200 return our isFalse() || other. isFalse() ? kleenean (our NO_) :
201 our isTrue() && other. isTrue() ? kleenean (our YES_) :
202 kleenean (our UNKNOWN);
203 }
204 kleenean operator|| (const kleenean other) const noexcept {
205 return our isTrue() || other. isTrue() ? kleenean (our YES_) :
206 our isFalse() && other. isFalse() ? kleenean (our NO_) :
207 kleenean (our UNKNOWN);
208 }
209 kleenean operator== (const kleenean other) const noexcept { // logical equivalence
210 return our isUnknown() || other. isUnknown() ? kleenean (our UNKNOWN) :
211 kleenean (our isTrue() == other. isTrue());
212 }
213 kleenean operator!= (const kleenean other) const noexcept {
214 return our isUnknown() || other. isUnknown() ? kleenean (our UNKNOWN) :
215 kleenean (our isTrue() != other. isTrue());
216 // this is the same as ! ( *this == other )
217 }
218 };
219 constexpr kleenean kleenean_UNKNOWN = kleenean (-1);
220 constexpr kleenean kleenean_NO = kleenean (0);
221 constexpr kleenean kleenean_YES = kleenean (1);
222
223 /* End of file melder_int.h */
224 #endif
225