1 /* Praat_tests.cpp
2  *
3  * Copyright (C) 2001-2007,2009,2011-2020 Paul Boersma
4  *
5  * This code is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  *
10  * This code is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this work. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /* December 10, 2006: MelderInfo */
20 /* November 5, 2007: wchar */
21 /* 21 March 2009: modern enums */
22 /* 24 May 2011: C++ */
23 /* 5 June 2015: char32 */
24 
25 #include "FileInMemoryManager.h"
26 #include "Praat_tests.h"
27 
28 #include "Graphics.h"
29 #include "praat.h"
30 #include "NUM2.h"
31 #include "Sound.h"
32 
33 #include "enums_getText.h"
34 #include "Praat_tests_enums.h"
35 #include "enums_getValue.h"
36 #include "Praat_tests_enums.h"
37 #include <string>
38 
39 static void testAutoData (autoDaata data) {
40 	fprintf (stderr, "testAutoData: %p %p\n", data.get(), data -> name.get());
41 }
42 static void testAutoDataRef (autoDaata& data) {
43 	fprintf (stderr, "testAutoDataRef: %p %p\n", data.get(), data -> name.get());
44 }
45 static void testData (Daata data) {
46 	fprintf (stderr, "testData: %p %s\n", data, Melder_peek32to8 (data -> name.get()));
47 }
48 static autoDaata newAutoData () {
49 	autoDaata data (Thing_new (Daata));
50 	return data;
51 }
52 static integer length (conststring32 s) {
53 	integer result = str32len (s);
54 	Melder_free (s);
55 	return result;
56 }
57 
58 static autoMAT constantHH (integer nrow, integer ncol, double value) {
59 	autoMAT result = raw_MAT (nrow, ncol);
60 	result.all()  <<=  value;
61 	return result;
62 }
63 
64 int Praat_tests (kPraatTests itest, conststring32 arg1, conststring32 arg2, conststring32 arg3, conststring32 arg4) {
65 	int64 n = Melder_atoi (arg1);
66 	double t = 0.0;
67 	(void) arg1;
68 	(void) arg2;
69 	(void) arg3;
70 	(void) arg4;
71 	Melder_clearInfo ();
72 	Melder_stopwatch ();
73 	switch (itest) {
74 		case kPraatTests::UNDEFINED:
75 		case kPraatTests::_:
76 		case kPraatTests::CHECK_RANDOM_1009_2009: {
77 		} break;
78 		case kPraatTests::TIME_RANDOM_FRACTION: {
79 			for (int64 i = 1; i <= n; i ++)
80 				(void) NUMrandomFraction ();
81 			t = Melder_stopwatch ();
82 		} break;
83 		case kPraatTests::TIME_RANDOM_GAUSS: {
84 			for (int64 i = 1; i <= n; i ++)
85 				(void) NUMrandomGauss (0.0, 1.0);
86 			t = Melder_stopwatch ();
87 		} break;
88 		case kPraatTests::TIME_SORT: {
89 			integer size = Melder_atoi (arg2);
90 			autoVEC array = raw_VEC (size);
91 			Melder_stopwatch ();
92 			for (int64 iteration = 1; iteration <= n; iteration ++) {
93 				for (int64 i = 1; i <= size; i ++)
94 					array [i] = NUMrandomFraction ();
95 				sort_VEC_inout (array.get());
96 			}
97 			t = Melder_stopwatch () / (size * log2 (size));
98 		} break;
99 		case kPraatTests::TIME_INTEGER: {
100 			int64 sum = 0;
101 			for (int64 i = 1; i <= n; i ++)
102 				sum += i * (i - 1) * (i - 2);
103 			t = Melder_stopwatch ();
104 			MelderInfo_writeLine (sum);
105 		} break;
106 		case kPraatTests::TIME_FLOAT: {
107 			double sum = 0.0, fn = n;
108 			for (double fi = 1.0; fi <= fn; fi += 1.0)
109 				sum += fi * (fi - 1.0) * (fi - 2.0);
110 			t = Melder_stopwatch ();   // 2.02 ns
111 			MelderInfo_writeLine (sum);
112 		} break;
113 		case kPraatTests::TIME_FLOAT_TO_UNSIGNED_BUILTIN: {
114 			uint64 sum = 0;
115 			double fn = n;
116 			for (double fi = 1.0; fi <= fn; fi += 1.0)
117 				sum += (uint32) fi;
118 			t = Melder_stopwatch ();   // 1.45 ns
119 			MelderInfo_writeLine (sum);
120 		} break;
121 		case kPraatTests::TIME_FLOAT_TO_UNSIGNED_EXTERN: {
122 			uint64 sum = 0;
123 			double fn = n;
124 			for (double fi = 1.0; fi <= fn; fi += 1.0)
125 				sum += (uint32) ((int32) (fi - 2147483648.0) + 2147483647L + 1);
126 			t = Melder_stopwatch ();   // 1.47 ns
127 			MelderInfo_writeLine (sum);
128 		} break;
129 		case kPraatTests::TIME_UNSIGNED_TO_FLOAT_BUILTIN: {
130 			double sum = 0.0;
131 			uint32 nu = (uint32) n;
132 			for (uint32 iu = 1; iu <= nu; iu ++)
133 				sum += (double) iu;
134 			t = Melder_stopwatch ();   // 0.88 ns
135 			MelderInfo_writeLine (sum);
136 		} break;
137 		case kPraatTests::TIME_UNSIGNED_TO_FLOAT_EXTERN: {
138 			double sum = 0.0;
139 			uint32 nu = (uint32) n;
140 			for (uint32 iu = 1; iu <= nu; iu ++)
141 				sum += (double) (int32) (iu - 2147483647L - 1) + 2147483648.0;
142 			t = Melder_stopwatch ();   // 0.87 ns
143 			MelderInfo_writeLine (sum);
144 		} break;
145 		case kPraatTests::TIME_STRING_MELDER_32: {
146 			autoMelderString string;
147 			char32 word [] { U"abc" };
148 			word [2] = char32 (NUMrandomInteger (U'a', U'z'));
149 			for (int64 i = 1; i <= n; i ++) {
150 				MelderString_copy (& string, word);
151 				for (int j = 1; j <= 30; j ++)
152 					MelderString_append (& string, word);
153 			}
154 			t = Melder_stopwatch ();
155 		} break;
156 		case kPraatTests::TIME_STRING_MELDER_32_ALLOC: {
157 			char32 word [] { U"abc" };
158 			word [2] = char32 (NUMrandomInteger (U'a', U'z'));
159 			for (int64 i = 1; i <= n; i ++) {
160 				autoMelderString string;
161 				MelderString_copy (& string, word);
162 				for (int j = 1; j <= 30; j ++)
163 					MelderString_append (& string, word);
164 			}
165 			t = Melder_stopwatch ();
166 		} break;
167 		case kPraatTests::TIME_STRING_CPP_S: {
168 			std::string s = "";
169 			char word [] { "abc" };
170 			word [2] = char (NUMrandomInteger ('a', 'z'));
171 			for (int64 i = 1; i <= n; i ++) {
172 				s = word;
173 				for (int j = 1; j <= 30; j ++)
174 					s += word;
175 			}
176 			t = Melder_stopwatch ();
177 		} break;
178 		case kPraatTests::TIME_STRING_CPP_C: {
179 			std::basic_string<char> s = "";
180 			char word [] { "abc" };
181 			word [2] = char (NUMrandomInteger ('a', 'z'));
182 			for (int64 i = 1; i <= n; i ++) {
183 				s = word;
184 				for (int j = 1; j <= 30; j ++)
185 					s += word;
186 			}
187 			t = Melder_stopwatch ();
188 		} break;
189 		case kPraatTests::TIME_STRING_CPP_WS: {
190 			std::wstring s = L"";
191 			wchar_t word [] { L"abc" };
192 			word [2] = wchar_t (NUMrandomInteger (L'a', L'z'));
193 			for (int64 i = 1; i <= n; i ++) {
194 				s = word;
195 				for (int j = 1; j <= 30; j ++)
196 					s += word;
197 			}
198 			t = Melder_stopwatch ();
199 		} break;
200 		case kPraatTests::TIME_STRING_CPP_WC: {
201 			std::basic_string<wchar_t> s = L"";
202 			wchar_t word [] { L"abc" };
203 			word [2] = wchar_t (NUMrandomInteger (L'a', L'z'));
204 			for (int64 i = 1; i <= n; i ++) {
205 				s = word;
206 				for (int j = 1; j <= 30; j ++)
207 					s += word;
208 			}
209 			t = Melder_stopwatch ();
210 		} break;
211 		case kPraatTests::TIME_STRING_CPP_32: {
212 			std::basic_string<char32_t> s = U"";
213 			char32 word [] { U"abc" };
214 			word [2] = char32 (NUMrandomInteger (U'a', U'z'));
215 			for (int64 i = 1; i <= n; i ++) {
216 				s = word;
217 				for (int j = 1; j <= 30; j ++)
218 					s += word;
219 			}
220 			t = Melder_stopwatch ();
221 		} break;
222 		case kPraatTests::TIME_STRING_CPP_U32STRING: {
223 			std::u32string s = U"";
224 			char32 word [] { U"abc" };
225 			word [2] = char32 (NUMrandomInteger (U'a', U'z'));
226 			for (int64 i = 1; i <= n; i ++) {
227 				s = word;
228 				for (int j = 1; j <= 30; j ++)
229 					s += word;
230 			}
231 			t = Melder_stopwatch ();
232 		} break;
233 		case kPraatTests::TIME_STRCPY: {
234 			char buffer [100];
235 			char word [] { "abc" };
236 			word [2] = (char) NUMrandomInteger ('a', 'z');
237 			for (int64 i = 1; i <= n; i ++) {
238 				strcpy (buffer, word);
239 				for (int j = 1; j <= 30; j ++)
240 					strcpy (buffer + strlen (buffer), word);
241 			}
242 			t = Melder_stopwatch ();
243 			MelderInfo_writeLine (Melder_peek8to32 (buffer));
244 		} break;
245 		case kPraatTests::TIME_WCSCPY: {
246 			wchar_t buffer [100];
247 			wchar_t word [] { L"abc" };
248 			word [2] = wchar_t (NUMrandomInteger (L'a', L'z'));
249 			for (int64 i = 1; i <= n; i ++) {
250 				wcscpy (buffer, word);
251 				for (int j = 1; j <= 30; j ++)
252 					wcscpy (buffer + wcslen (buffer), word);
253 			}
254 			t = Melder_stopwatch ();
255 		} break;
256 		case kPraatTests::TIME_STR32CPY: {
257 			char32 buffer [100];
258 			char32 word [] { U"abc" };
259 			word [2] = char32 (NUMrandomInteger (U'a', U'z'));
260 			for (int64 i = 1; i <= n; i ++) {
261 				str32cpy (buffer, word);
262 				for (int j = 1; j <= 30; j ++)
263 					str32cpy (buffer + str32len (buffer), word);
264 			}
265 			t = Melder_stopwatch ();
266 			MelderInfo_writeLine (buffer);
267 		} break;
268 		case kPraatTests::TIME_GRAPHICS_TEXT_TOP: {
269 			autoPraatPicture picture;
270 			for (int64 i = 1; i <= n; i ++) {
271 				Graphics_textTop (GRAPHICS, false, U"hello world");
272 			}
273 			t = Melder_stopwatch ();
274 		} break;
275 		case kPraatTests::TIME_UNDEFINED_NUMUNDEFINED: {
276 			bool isAllDefined = true;
277 			double x = 0.0;
278 			for (int64 i = 1; i <= n; i ++) {
279 				x += (double) i;
280 				isAllDefined &= ( x != undefined );
281 			}
282 			t = Melder_stopwatch ();   // 0.86 ns
283 			MelderInfo_writeLine (isAllDefined, U" ", x);
284 		} break;
285 		case kPraatTests::TIME_UNDEFINED_ISINF_OR_ISNAN: {
286 			bool isAllDefined = true;
287 			double x = 0.0;
288 			for (int64 i = 1; i <= n; i ++) {
289 				x += (double) i;
290 				isAllDefined &= ! std::isinf (x) && ! std::isnan (x);
291 				//isAllDefined &= ! isfinite (x);   // same
292 			}
293 			t = Melder_stopwatch ();   // 1.29 ns
294 			MelderInfo_writeLine (isAllDefined, U" ", x);
295 		} break;
296 		case kPraatTests::TIME_UNDEFINED_0x7FF: {
297 			bool isAllDefined = true;
298 			double x = 0.0;
299 			for (int64 i = 1; i <= n; i ++) {
300 				x += (double) i;
301 				isAllDefined &= ((* (uint64 *) & x) & 0x7FF0'0000'0000'0000) != 0x7FF0'0000'0000'0000;
302 			}
303 			t = Melder_stopwatch ();   // 0.90 ns
304 			MelderInfo_writeLine (isAllDefined, U" ", x);
305 		} break;
306 		case kPraatTests::TIME_INNER: {
307 			integer size = Melder_atoi (arg2);
308 			autoVEC x = randomGauss_VEC (size, 0.0, 1.0);
309 			autoVEC y = randomGauss_VEC (size, 0.0, 1.0);
310 			double z = 0.0;
311 			for (int64 i = 1; i <= n; i ++)
312 				z += NUMinner (x.get(), y.get());
313 			t = Melder_stopwatch () / size;   // 2.9 Gops = 5.8 Gflops (multiplication-addition pair)
314 			MelderInfo_writeLine (z);
315 		} break;
316 		case kPraatTests::TIME_OUTER_NUMMAT: {
317 			integer nrow = 100, ncol = 100;
318 			autoVEC x = randomGauss_VEC (nrow, 0.0, 1.0);
319 			autoVEC y = randomGauss_VEC (ncol, 0.0, 1.0);
320 			for (int64 i = 1; i <= n; i ++)
321 				const autoMAT mat = outer_MAT (x.get(), y.get());
322 			t = Melder_stopwatch () / nrow / ncol;   // 6.1 Gops, i.e. less than one clock cycle per cell
323 		} break;
324 		case kPraatTests::CHECK_INVFISHERQ: {
325 			MelderInfo_writeLine (NUMinvFisherQ (0.003, 1, 100000));
326 		} break;
327 		case kPraatTests::TIME_AUTOSTRING: {
328 			conststring32 strings [6] = { U"ghdg", U"jhd", U"hkfjjd", U"fhfj", U"jhksfd", U"hfjs" };
329 			int64 sumOfLengths = 0;
330 			for (int64 i = 1; i <= n; i ++) {
331 				int istring = i % 6;
332 				autostring32 s = Melder_dup (strings [istring]);
333 				sumOfLengths += length (s.transfer());
334 			}
335 			t = Melder_stopwatch ();   // 72 ns (but 152 bytes more)
336 			MelderInfo_writeLine (sumOfLengths);
337 		} break;
338 		case kPraatTests::TIME_CHAR32: {
339 			conststring32 strings [6] = { U"ghdg", U"jhd", U"hkfjjd", U"fhfj", U"jhksfd", U"hfjs" };
340 			int64 sumOfLengths = 0;
341 			for (int64 i = 1; i <= n; i ++) {
342 				int istring = i % 6;
343 				char32 *s = Melder_dup (strings [istring]).transfer();
344 				sumOfLengths += length (s);
345 			}
346 			t = Melder_stopwatch ();   // 72 ns
347 			MelderInfo_writeLine (sumOfLengths);
348 		} break;
349 		case kPraatTests::TIME_SUM: {
350 			integer size = Melder_atoi (arg2);
351 			autoVEC x = randomGauss_VEC (size, 0.0, 1.0);
352 			double z = 0.0;
353 			for (int64 i = 1; i <= n; i ++) {
354 				double sum = NUMsum (x.get());
355 				z += sum;
356 			}
357 			t = Melder_stopwatch () / size;   // for size == 100: 0.31 ns
358 			MelderInfo_writeLine (z);
359 		} break;
360 		case kPraatTests::TIME_MEAN: {
361 			integer size = Melder_atoi (arg2);
362 			autoVEC x = randomGauss_VEC (size, 0.0, 1.0);
363 			double z = 0.0;
364 			for (int64 i = 1; i <= n; i ++) {
365 				double sum = NUMmean (x.get());
366 				z += sum;
367 			}
368 			t = Melder_stopwatch () / size;   // for size == 100: 0.34 ns
369 			MelderInfo_writeLine (z);
370 		} break;
371 		case kPraatTests::TIME_STDEV: {
372 			integer size = 10000;
373 			autoVEC x = randomGauss_VEC (size, 0.0, 1.0);
374 			double z = 0.0;
375 			for (int64 i = 1; i <= n; i ++) {
376 				double stdev = NUMstdev (x.get());
377 				z += stdev;
378 			}
379 			t = Melder_stopwatch () / size;
380 			MelderInfo_writeLine (z);
381 		} break;
382 		case kPraatTests::TIME_ALLOC: {
383 			integer size = Melder_atoi (arg2);
384 			for (int64 iteration = 1; iteration <= n; iteration ++) {
385 				autoVEC result = raw_VEC (size);
386 				for (integer i = 1; i <= size; i ++)
387 					result [i] = 0.0;
388 			}
389 			t = Melder_stopwatch () / size;   // 10^0..7: 70/6.9/1.08 / 0.074/0.0074/0.0091 / 0.51/0.00026 ns
390 		} break;
391 		case kPraatTests::TIME_ALLOC0: {
392 			integer size = Melder_atoi (arg2);
393 			for (int64 iteration = 1; iteration <= n; iteration ++)
394 				autoVEC result = zero_VEC (size);
395 			t = Melder_stopwatch () / size;   // 10^0..7: 76/7.7/1.23 / 0.165/0.24/0.25 / 1.30/1.63 ns
396 		} break;
397 		case kPraatTests::TIME_ZERO: {
398 			integer size = Melder_atoi (arg2);
399 			autoVEC result = raw_VEC (size);
400 			double z = 0.0;
401 			for (int64 iteration = 1; iteration <= n; iteration ++) {
402 				for (integer i = 1; i <= size; i ++)
403 					result [i] = (double) i;
404 				z += result [size - 1];
405 			}
406 			t = Melder_stopwatch () / size;
407 			MelderInfo_writeLine (z);
408 		} break;
409 		case kPraatTests::TIME_MALLOC: {
410 			integer size = Melder_atoi (arg2);
411 			double value = Melder_atof (arg3);
412 			double z = 0.0;
413 			for (int64 iteration = 1; iteration <= n; iteration ++) {
414 				double *result = (double *) malloc (sizeof (double) * (size_t) size);
415 				for (integer i = 0; i < size; i ++)
416 					result [i] = value;
417 				z += result [size / 2];
418 				free (result);
419 			}
420 			t = Melder_stopwatch () / size;
421 			MelderInfo_writeLine (z);
422 		} break;
423 		case kPraatTests::TIME_CALLOC: {
424 			integer size = Melder_atoi (arg2);
425 			double z = 0.0;
426 			for (integer iteration = 1; iteration <= n; iteration ++) {
427 				double *result = (double *) calloc (sizeof (double), (size_t) size);
428 				z += result [size / 2];
429 				free (result);
430 			}
431 			t = Melder_stopwatch () / size;
432 			MelderInfo_writeLine (z);
433 		} break;
434 		case kPraatTests::TIME_ADD: {
435 			integer size = Melder_atoi (arg2);
436 			autoMAT result = randomGauss_MAT (size, size, 0.0, 1.0);
437 			Melder_stopwatch ();
438 			for (integer iteration = 1; iteration <= n; iteration ++)
439 				result.all()  <<=  5.0;
440 			t = Melder_stopwatch () / size / size;   // 10^0..4: 2.7/0.16/0.24 / 0.38/0.98
441 			double sum = NUMsum (result.get());
442 			MelderInfo_writeLine (sum);
443 		} break;
444 		case kPraatTests::TIME_SIN: {
445 			integer size = Melder_atoi (arg2);
446 			autoMAT result = randomGauss_MAT (size, size, 0.0, 1.0);
447 			Melder_stopwatch ();
448 			for (integer iteration = 1; iteration <= n; iteration ++)
449 				sin_MAT_inout (result.get());
450 			t = Melder_stopwatch () / size / size;   // 10^0..4: 18/5.3/5.2 / 5.3/12
451 			double sum = NUMsum (result.get());
452 			MelderInfo_writeLine (sum);
453 		} break;
454 		case kPraatTests::TIME_VECADD: {
455 			integer size = Melder_atoi (arg2);
456 			autoVEC x = randomGauss_VEC (size, 0.0, 1.0);
457 			autoVEC y = randomGauss_VEC (size, 0.0, 1.0);
458 			autoVEC result = raw_VEC (size);
459 			Melder_stopwatch ();
460 			for (integer iteration = 1; iteration <= n; iteration ++)
461 				//add_VEC_out (result.all(), x.all(), y.all());
462 				result.all()  <<=  x.all() + y.all();
463 			t = Melder_stopwatch () / size;
464 			double sum = NUMsum (result.get());
465 			MelderInfo_writeLine (sum);
466 		} break;
467 		case kPraatTests::TIME_MATMUL: {
468 			const integer size1 = Melder_atoi (arg2);
469 			integer size2 = Melder_atoi (arg3);
470 			integer size3 = Melder_atoi (arg4);
471 			if (size2 == 0 || size3 == 0) size3 = size2 = size1;
472 			//autoMAT const x = randomGauss_MAT (size1, size2, 0.0, 1.0);
473 			//autoMAT const y = randomGauss_MAT (size2, size3, 0.0, 1.0);
474 			autoMAT x = constantHH (size1, size2, 10.0);
475 			autoMAT y = constantHH (size2, size3, 3.0);
476 			autoMAT const result = raw_MAT (size1, size3);
477 			//MAT resultget = result.get();
478 			//constMAT xget = x.get(), yget = y.get();
479 			MATVU const result_all = result.all();
480 			constMATVU const x_all = x.all();
481 			constMATVU const y_all = y.all();
482 			Melder_stopwatch ();
483 			for (integer iteration = 1; iteration <= n; iteration ++)
484 				//MATmul_forceMetal_ (result_all, x_all, y_all);
485 				_mul_allowAllocation_MAT_out (result_all, x_all, y_all);
486 			const integer numberOfComputations = size1 * size2 * size3 * 2;
487 			t = Melder_stopwatch () / numberOfComputations;
488 			const double sum = NUMsum (result.get());
489 			const integer numberOfStores = size1 * size2 + size2 * size3 + size1 * size3 + 10000;
490 			MelderInfo_writeLine (double (numberOfComputations) / double (numberOfStores), U" computations per store");
491 			MelderInfo_writeLine (sum, U" should be ", size1 * size2 * size3 * 30.0);
492 			//Melder_require (NUMequal (result.get(), constantHH (size, size, size * 30.0).get()), U"...");
493 		} break;
494 		case kPraatTests::THING_AUTO: {
495 			integer numberOfThingsBefore = theTotalNumberOfThings;
496 			{
497 				Melder_casual (U"1\n");
498 				autoDaata data = Thing_new (Daata);
499 				Thing_setName (data.get(), U"hello");
500 				Melder_casual (U"2\n");
501 				testData (data.get());
502 				testAutoData (data.move());
503 				autoDaata data18 = Thing_new (Daata);
504 				testAutoData (data18.move());
505 				fprintf (stderr, "3\n");
506 				autoDaata data2 = newAutoData ();
507 				fprintf (stderr, "4\n");
508 				autoDaata data3 = newAutoData ();
509 				fprintf (stderr, "5\n");
510 				//data2 = data;   // disabled l-value copy assignment from same class
511 				fprintf (stderr, "6\n");
512 				autoOrdered ordered = Thing_new (Ordered);
513 				fprintf (stderr, "7\n");
514 				//data = ordered;   // disabled l-value copy assignment from subclass
515 				data = ordered.move();
516 				//ordered = data;   // disabled l-value copy assignment from superclass
517 				//ordered = data.move();   // assignment from superclass to subclass is rightfully refused by compiler
518 				fprintf (stderr, "8\n");
519 				data2 = newAutoData ();
520 				fprintf (stderr, "8a\n");
521 				autoDaata data5 = newAutoData ();
522 				fprintf (stderr, "8b\n");
523 				data2 = data5.move();
524 				fprintf (stderr, "9\n");
525 				//ordered = data;   // rightfully refused by compiler
526 				fprintf (stderr, "10\n");
527 				//autoOrdered ordered2 = Thing_new (Daata);   // rightfully refused by compiler
528 				fprintf (stderr, "11\n");
529 				autoDaata data4 = Thing_new (Ordered);   // constructor
530 				fprintf (stderr, "12\n");
531 				//autoDaata data6 = data4;   // disabled l-value copy constructor from same class
532 				fprintf (stderr, "13\n");
533 				autoDaata data7 = data4.move();
534 				fprintf (stderr, "14\n");
535 				autoOrdered ordered3 = Thing_new (Ordered);
536 				autoDaata data8 = ordered3.move();
537 				fprintf (stderr, "15\n");
538 				//autoDaata data9 = ordered;   // disabled l-value copy constructor from subclass
539 				fprintf (stderr, "16\n");
540 				autoDaata data10 = data7.move();
541 				fprintf (stderr, "17\n");
542 				autoDaata data11 = Thing_new (Daata);   // constructor, move assignment, null destructor
543 				fprintf (stderr, "18\n");
544 				data11 = Thing_new (Ordered);
545 				fprintf (stderr, "19\n");
546 				testAutoDataRef (data11);
547 				fprintf (stderr, "20\n");
548 				//data11 = nullptr;   // disabled implicit assignment of pointer to autopointer
549 				fprintf (stderr, "21\n");
550 			}
551 			integer numberOfThingsAfter = theTotalNumberOfThings;
552 			fprintf (stderr, "Number of things: before %ld, after %ld\n",
553 					(long_not_integer) numberOfThingsBefore, (long_not_integer) numberOfThingsAfter);
554 			#if 0
555 				MelderCallback<void,structDaata>::FunctionType f;
556 				typedef void (*DataFunc) (Daata);
557 				typedef void (*OrderedFunc) (Ordered);
558 				DataFunc dataFun;
559 				OrderedFunc orderedFun;
560 				MelderCallback<void,structDaata> dataFun2 (dataFun);
561 				MelderCallback<void,structOrdered> orderedFun2 (orderedFun);
562 				MelderCallback<void,structDaata> dataFun3 (orderedFun);
563 				//MelderCallback<void,structOrdered> orderedFun3 (dataFun);   // rightfully refused by compiler
564 				autoDaata data = Thing_new (Daata);
565 				dataFun3 (data.get());
566 			#endif
567 			{
568 				#if 1
569 				autoMelderAsynchronous x;
570 				//autoMelderAsynchronous y = x;   // deleted copy constructor
571 				autoMelderAsynchronous y = x.move();   // defined move constructor
572 				//x = y;   // deleted copy assignment
573 				x = y.move();   // defined move assignment
574 				autoVEC a;
575 				autoVEC b = a.move();
576 				const autoVEC c;
577 				const autoVEC d { };
578 				#if 0
579 				double *e;
580 				const autoVEC f { e, 10 };
581 				#endif
582 				{
583 					autoVEC g = zero_VEC (100);
584 					g [1] = 3.0;
585 					VEC gg = g.get();
586 					gg [2] = 4.0;
587 					constVEC ggg = g.get();
588 					//ggg [3] = 5.0;   // should be refused by the compiler
589 					const VEC gggg = g.get();
590 					//gggg [3] = 6.0;   // should be refused by the compiler
591 					//return f;   // call to deleted constructor
592 					//gggg.reset();   // should be refused by the compiler
593 					//ggg.reset();   // should be refused by the compiler
594 					//gg.reset();
595 				}
596 				{
597 					double x [3], *px = & x [0];
598 					const double *cpx = px;
599 					VEC vx (px, 2);
600 					constVEC cvx (px, 2);
601 					const VEC c_vx (px, 2);
602 					double a = c_vx [1];
603 					const double b = c_vx [2];
604 					const double y = 0.0, *py = & y;
605 					//VEC vy (py, 0);   // ruled out: "No matching constructor for initialization of VEC" (2021-04-03)
606 					constVEC cvy { py, 2 };
607 					//const VEC c_vy = VEC (py, 2);   // ruled out: "No matching constructor for initialization of VEC" (2021-04-03)
608 					const VEC c_vy = (const VEC) VEC (const_cast<double *> (py), 2);
609 					double c = c_vy [1];
610 					const double d = c_vy [2];
611 					//VEC c_vy2 = VEC (py, 2);   // ruled out: "No matching constructor for initialization of VEC" (2021-04-03)
612 				}
613 
614 				VEC h;
615 				autoVEC j;
616 				//VEC jh = j;   // ruled out: "No viable conversion from autoVEC to VEC" (2021-04-03)
617 				//VEC zero = zero_VEC (10);   // ruled out: "No viable conversion from autoVEC to VEC" (2021-04-03)
618 				//constVEC zero = zero_VEC (10);   // ruled out: "No viable conversion from autoVEC to constVEC" (2021-04-03)
619 				//j = h;   // ruled out: "No viable overloaded '='" (2021-04-03)
620 				//h = j;   // ruled out: "No viable overloaded '='" (2021-04-03)
621 				//h = VEC (j);   // ruled out: "No matching conversion for functional-style cast from autoVEC to VEC" (2021-04-03)
622 				//VEC & jref = j;   // ruled out: "Non-const lvalue reference to type VEC cannot bind to a value of unrelated type autoVEC" (2021-04-03)
623 				VEC *ph = & h;
624 				autoVEC *pj = & j;
625 				//ph = pj;   // correctly ruled out: Assigning to 'VEC' from incompatible type 'autoVEC' (2021-04-03)
626 				//pj = ph;   // correctly ruled out: "Assigning to 'autoVEC *' from incompatible type 'VEC *' (2021-04-03)
627 				#endif
628 				autoSound sound = Sound_create (1, 0.0, 1.0, 10000, 0.0001, 0.0);
629 				sound = Sound_create (1, 0.0, 1.0, 10000, 0.0001, 0.00005);
630 				Melder_casual (U"hello ", sound -> dx);
631 				autoSTRVEC v;
632 				mutablestring32 *pm = v.peek2();
633 				const mutablestring32 *pcm = v.peek2();
634 				//conststring32 *pc = v.peek2();
635 				const conststring32 *pcc = v.peek2();
636 				{
637 					vector<double> aa, bb;
638 					vector<const double> aac, bbc;
639 					//aa = aac;
640 					aa = bb;
641 					aac = bbc;
642 					bbc.cells = bb.cells;
643 				}
644 			}
645 		} break;
646 		case kPraatTests::FILEINMEMORYMANAGER_IO: {
647 			test_FileInMemoryManager_io ();
648 		} break;
649 	}
650 	MelderInfo_writeLine (Melder_single (n / t * 1e-9), U" Gflop/s");
651 	MelderInfo_close ();
652 	return 1;
653 }
654 
655 /* More compiler stuff */
656 #if 1
657 /*
658 	Trying out inheritance without encapsulation...
659 	Advantage: everything is a method; therefore, the Law of Demeter is satisfied idiomatically
660 	Disadvantage: problematic encapsulation
661 */
662 Thing_declare (Matrix_);
663 Thing_declare (Sound_);
664 Thing_declare (Pitch_);
665 
666 /*
667 	The following two sets of files have to be included
668 	in Pitch_to_Sound.cpp as well as in Sound_to_Pitch.cpp,
669 	but can come in either order:
670 */
671 
672 /*
673 	Set 1: Pitch.h
674 */
675 struct structPitch_ : structThing {
676 	double f0;
677 	autoSound_ toSound ();   // anti-encapsulation
678 };
679 
680 /*
681 	Set 2: Matrix.h followed by Sound.h
682 */
683 struct structMatrix_ : structThing {
684 	private: double x, y;
685 	public: double getX () { return x; }
686 	void setX (double newX) { x = newX; }
687 };
688 struct structSound_ : public structMatrix_ {   // the definition of structSound_ requires the prior definition of structMatrix_
689 	autoPitch_ toPitch ();   // anti-encapsulation
690 };
691 
692 /*
693 	The following two files are independent of each other:
694 */
695 
696 /*
697 	Pitch_to_Sound.cpp:
698 	#include "Pitch.h"
699 	#include "Sound.h"
700 */
701 autoSound_ structPitch_::toSound () {   // this requires the prior definition of structPitch_ and the prior declaration of structSound_
702 	autoSound_ result = autoSound_ ();
703 	result -> setX (f0);   // this requires the prior definition of structSound_ and structMatrix_
704 	return result;
705 }
706 
707 /*
708 	Sound_to_Pitch.cpp:
709 	#include "Sound.h"
710 	#include "Pitch.h"
711 */
712 autoPitch_ structSound_::toPitch () {   // this requires the prior definition of structSound_ and the prior declaration of structPitch_
713 	double x = getX ();   // this requires the prior definition of structSound_ and structMatrix_
714 	autoPitch_ result = autoPitch_ ();
715 	result -> f0 = x;   // this requires the prior definition of structPitch_
716 	return result;
717 }
718 
719 #endif
720 
721 /*
722 	An attempt to not have VEC and constVEC, but VEC and const VEC instead.
723 */
724 
725 class Vec {
726 public:
727 	double *at;
728 	integer size;
729 	const double *const_propagate_at () const { return at; }
730 	double *const_propagate_at () { return at; }
731 public:
732 	Vec (double *initialAt, integer initialSize) : at (initialAt), size (initialSize) { }
733 	double& operator[] (integer index) { return at [index]; }   // selected for Vec (1)
734 	const double& operator[] (integer index) const { return at [index]; }   // selected for const Vec (2)
735 	//Vec (Vec& other) : at (other.const_propagate_at()), size (other.size) { };   // can assign Vec to Vec (3)
736 	//Vec (Vec&& other) : at (other.at), size (other.size) { };   // can assign Vec to Vec (3)
737 	Vec (Vec& other) : at (other.at), size (other.size) { };   // can assign Vec to Vec (3)
738 	Vec (const Vec& other) = delete;   // cannot assign const Vec to Vec (4)
739 		/* unfortunately, this also precludes initializing a *const* Vec from a const Vec */
740 	//Vec (const Vec& other) const = default;   // attempt to copy a const Vec to a const Vec, but constructors cannot be const
741 	//const Vec (const Vec& other) = default;   // attempt to copy a const Vec to a const Vec, but constructors cannot have a return type
742 };
743 
744 static Vec copy (Vec x) {
745 	return Vec(x);
746 }
747 
748 /*static void tryVec () {
749 	Vec x = Vec (nullptr, 0);
750 	x [1] = 3.0;
751 	double a = x [2];
752 	const Vec cx = Vec (nullptr, 0);
753 	//cx [1] = 3.0;   // should be refused by compiler, because operator[] returns a const value that cannot be assigned to (2)
754 	a = cx [2];   // should be allowed by compiler, because not an assignment (2)
755 	const Vec cy = x;   // should be allowed (3)
756 	//Vec y = cx;   // should be refused (4)
757 	const Vec cz = copy (x);
758 	//cx.at [1] = 3.0;
759 	////const Vec ca = cy;   // should be allowed
760 }*/
761 
762 /* End of file Praat_tests.cpp */
763