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