1 /*
2  * Copyright (c) 2013-2021, The OSKAR Developers.
3  * See the LICENSE file at the top-level directory of this distribution.
4  */
5 
6 #include <gtest/gtest.h>
7 
8 #include "utility/oskar_get_error_string.h"
9 #include "mem/oskar_mem.h"
10 #include <cstdio>
11 
TEST(Mem,load_ascii_single_column)12 TEST(Mem, load_ascii_single_column)
13 {
14     int status = 0;
15 
16     // Write a test file.
17     const char* filename = "temp_test_load_ascii_single_column.txt";
18     FILE* file = fopen(filename, "w");
19     ASSERT_TRUE(file != NULL);
20     size_t i = 0, num_elements = 13;
21     fprintf(file, "# A header\n");
22     for (; i < num_elements; ++i) fprintf(file, "%.3f\n", i * 1.0);
23     fprintf(file, "# A comment\n");
24     for (; i < 2 * num_elements; ++i) fprintf(file, "%.3f\n", i * 1.0);
25     fprintf(file, "  # A silly comment\n");
26     for (; i < 3 * num_elements; ++i) fprintf(file, "%.3f\n", i * 1.0);
27     fclose(file);
28 
29     // Load column back into CPU memory.
30     oskar_Mem *a = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
31     ASSERT_EQ(0, status) << oskar_get_error_string(status);
32     oskar_mem_load_ascii(filename, 1, &status, a, "");
33     ASSERT_EQ(0, status) << oskar_get_error_string(status);
34     ASSERT_EQ(3 * num_elements, oskar_mem_length(a));
35 
36     // Check contents.
37     const double* a_ = oskar_mem_double_const(a, &status);
38     for (i = 0; i < 3 * num_elements; ++i)
39     {
40         ASSERT_NEAR(a_[i], i * 1.0, 1e-10);
41     }
42 
43     oskar_mem_free(a, &status);
44     remove(filename);
45 }
46 
TEST(Mem,load_ascii_real_cpu)47 TEST(Mem, load_ascii_real_cpu)
48 {
49     int status = 0;
50 
51     // Write a test file.
52     const char* filename = "temp_test_load_ascii_real.txt";
53     FILE* file = fopen(filename, "w");
54     ASSERT_TRUE(file != NULL);
55     int num_elements = 287;
56     for (int i = 0; i < num_elements; ++i)
57     {
58         fprintf(file, "%.3f %.3f %.3f, %.5e\n", i * 1.0, i * 10.0, i * 100.0,
59                 i * 1000.0);
60     }
61     fclose(file);
62 
63     // Load columns back into CPU memory.
64     oskar_Mem *a = 0, *b = 0, *c = 0, *d = 0;
65     a = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
66     b = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
67     c = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
68     d = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
69     ASSERT_EQ(0, status) << oskar_get_error_string(status);
70 
71     // Expect pass.
72     oskar_mem_load_ascii(filename, 4, &status, a, "0.0", b, "0.0",
73             c, "0.0", d, "0.0");
74     ASSERT_EQ(0, status) << oskar_get_error_string(status);
75 
76     // Check contents.
77     const double* a_ = oskar_mem_double_const(a, &status);
78     const double* b_ = oskar_mem_double_const(b, &status);
79     const double* c_ = oskar_mem_double_const(c, &status);
80     const double* d_ = oskar_mem_double_const(d, &status);
81     for (int i = 0; i < num_elements; ++i)
82     {
83         ASSERT_NEAR(a_[i], i * 1.0, 1e-10);
84         ASSERT_NEAR(b_[i], i * 10.0, 1e-10);
85         ASSERT_NEAR(c_[i], i * 100.0, 1e-10);
86         ASSERT_NEAR(d_[i], i * 1000.0, 1e-10);
87     }
88 
89     oskar_mem_free(a, &status);
90     oskar_mem_free(b, &status);
91     oskar_mem_free(c, &status);
92     oskar_mem_free(d, &status);
93 
94     remove(filename);
95 }
96 
97 
98 #ifdef OSKAR_HAVE_CUDA
TEST(Mem,load_ascii_real_gpu)99 TEST(Mem, load_ascii_real_gpu)
100 {
101     int status = 0;
102 
103     // Write a test file.
104     const char* filename = "temp_test_load_ascii_real_gpu.txt";
105     FILE* file = fopen(filename, "w");
106     ASSERT_TRUE(file != NULL);
107     int num_elements = 474;
108     for (int i = 0; i < num_elements; ++i)
109     {
110         fprintf(file, "%.3f %.3f %.3f, %.5e\n", i * 1.0, i * 10.0, i * 100.0,
111                 i * 1000.0);
112     }
113     fclose(file);
114 
115     // Load columns back into GPU memory.
116     oskar_Mem *a = 0, *b = 0, *c = 0, *d = 0;
117     a = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, 0, &status);
118     b = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, 0, &status);
119     c = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, 0, &status);
120     d = oskar_mem_create(OSKAR_DOUBLE, OSKAR_GPU, 0, &status);
121     ASSERT_EQ(0, status) << oskar_get_error_string(status);
122 
123     // Expect pass.
124     oskar_mem_load_ascii(filename, 4, &status, a, "0.0", b, "0.0",
125             c, "0.0", d, "0.0");
126     ASSERT_EQ(0, status) << oskar_get_error_string(status);
127 
128     // Copy to CPU memory to check contents.
129     oskar_Mem *aa = 0, *bb = 0, *cc = 0, *dd = 0;
130     aa = oskar_mem_create_copy(a, OSKAR_CPU, &status);
131     bb = oskar_mem_create_copy(b, OSKAR_CPU, &status);
132     cc = oskar_mem_create_copy(c, OSKAR_CPU, &status);
133     dd = oskar_mem_create_copy(d, OSKAR_CPU, &status);
134     const double* a_ = oskar_mem_double_const(aa, &status);
135     const double* b_ = oskar_mem_double_const(bb, &status);
136     const double* c_ = oskar_mem_double_const(cc, &status);
137     const double* d_ = oskar_mem_double_const(dd, &status);
138     for (int i = 0; i < num_elements; ++i)
139     {
140         ASSERT_NEAR(a_[i], i * 1.0, 1e-10);
141         ASSERT_NEAR(b_[i], i * 10.0, 1e-10);
142         ASSERT_NEAR(c_[i], i * 100.0, 1e-10);
143         ASSERT_NEAR(d_[i], i * 1000.0, 1e-10);
144     }
145 
146     oskar_mem_free(a, &status);
147     oskar_mem_free(b, &status);
148     oskar_mem_free(c, &status);
149     oskar_mem_free(d, &status);
150     oskar_mem_free(aa, &status);
151     oskar_mem_free(bb, &status);
152     oskar_mem_free(cc, &status);
153     oskar_mem_free(dd, &status);
154 
155     remove(filename);
156 }
157 #endif
158 
159 
TEST(Mem,load_ascii_complex_real_cpu)160 TEST(Mem, load_ascii_complex_real_cpu)
161 {
162     int status = 0;
163 
164     // Write a test file.
165     const char* filename = "temp_test_load_ascii_complex_real_cpu.txt";
166     FILE* file = fopen(filename, "w");
167     ASSERT_TRUE(file != NULL);
168     int num_elements = 326;
169     for (int i = 0; i < num_elements; ++i)
170     {
171         fprintf(file, "%.3f %.3f, %.5e\n", i * 1.0, i * 10.0, i * 100.0);
172     }
173     fclose(file);
174 
175     // Load columns back into CPU memory.
176     oskar_Mem *a = 0, *b = 0;
177     a = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU, 0, &status);
178     b = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
179     ASSERT_EQ(0, status) << oskar_get_error_string(status);
180 
181     // Wrong default: expect failure.
182     oskar_mem_load_ascii(filename, 2, &status, a, "1.0", b, "0.0");
183     ASSERT_NE(0, status);
184     status = 0;
185 
186     // Expect pass.
187     oskar_mem_load_ascii(filename, 2, &status, a, "1.0 0.0", b, "0.0");
188     ASSERT_EQ(0, status) << oskar_get_error_string(status);
189 
190     // Check contents.
191     const double2* a_ = oskar_mem_double2_const(a, &status);
192     const double* b_ = oskar_mem_double_const(b, &status);
193     for (int i = 0; i < num_elements; ++i)
194     {
195         ASSERT_NEAR(a_[i].x, i * 1.0, 1e-10);
196         ASSERT_NEAR(a_[i].y, i * 10.0, 1e-10);
197         ASSERT_NEAR(b_[i], i * 100.0, 1e-10);
198     }
199 
200     oskar_mem_free(a, &status);
201     oskar_mem_free(b, &status);
202 
203     remove(filename);
204 }
205 
206 
207 #ifdef OSKAR_HAVE_CUDA
TEST(Mem,load_ascii_complex_real_gpu_cpu)208 TEST(Mem, load_ascii_complex_real_gpu_cpu)
209 {
210     int status = 0;
211 
212     // Write a test file.
213     const char* filename = "temp_test_load_ascii_complex_real_gpu_cpu.txt";
214     FILE* file = fopen(filename, "w");
215     ASSERT_TRUE(file != NULL);
216     int num_elements = 753;
217     for (int i = 0; i < num_elements; ++i)
218     {
219         fprintf(file, "%.3f %.3f, %.5e\n", i * 1.0, i * 10.0, i * 100.0);
220     }
221     fclose(file);
222 
223     // Load columns back into CPU memory.
224     oskar_Mem *a = 0, *b = 0;
225     a = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_GPU, 0, &status);
226     b = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
227     ASSERT_EQ(0, status) << oskar_get_error_string(status);
228 
229     // Wrong default: expect failure.
230     oskar_mem_load_ascii(filename, 2, &status, a, "1.0", b, "0.0");
231     ASSERT_NE(0, status);
232     status = 0;
233 
234     // Expect pass.
235     oskar_mem_load_ascii(filename, 2, &status, a, "1.0 0.0", b, "0.0");
236     ASSERT_EQ(0, status) << oskar_get_error_string(status);
237 
238     // Check contents.
239     oskar_Mem *aa = oskar_mem_create_copy(a, OSKAR_CPU, &status);
240     const double2* a_ = oskar_mem_double2_const(aa, &status);
241     const double* b_ = oskar_mem_double_const(b, &status);
242     for (int i = 0; i < num_elements; ++i)
243     {
244         ASSERT_NEAR(a_[i].x, i * 1.0, 1e-10);
245         ASSERT_NEAR(a_[i].y, i * 10.0, 1e-10);
246         ASSERT_NEAR(b_[i], i * 100.0, 1e-10);
247     }
248 
249     oskar_mem_free(a, &status);
250     oskar_mem_free(b, &status);
251     oskar_mem_free(aa, &status);
252 
253     remove(filename);
254 }
255 #endif
256 
257 
TEST(Mem,load_ascii_complex_real_default_cpu)258 TEST(Mem, load_ascii_complex_real_default_cpu)
259 {
260     int status = 0;
261 
262     // Write a test file.
263     const char* filename = "temp_test_load_ascii_complex_real_default_cpu.txt";
264     FILE* file = fopen(filename, "w");
265     ASSERT_TRUE(file != NULL);
266     int num_elements = 89;
267     for (int i = 0; i < num_elements; ++i)
268     {
269         fprintf(file, "%.3f %.3f\n", i * 1.0, i * 10.0);
270     }
271     fclose(file);
272 
273     // Load columns back into CPU memory.
274     oskar_Mem *a = 0, *b = 0, *c = 0;
275     a = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU, 0, &status);
276     b = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
277     c = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
278     ASSERT_EQ(0, status) << oskar_get_error_string(status);
279 
280     // Wrong default: expect failure.
281     oskar_mem_load_ascii(filename, 2, &status, a, "1.0", b, "0.0");
282     ASSERT_NE(0, status);
283     status = 0;
284 
285     // Badly placed default: expect failure.
286     oskar_mem_load_ascii(filename, 3, &status, a, "", b, "9.9", c, "");
287     ASSERT_NE(0, status);
288     status = 0;
289 
290     // Expect pass.
291     oskar_mem_load_ascii(filename, 3, &status, a, "1.0 0.0", b, "5.1", c, "2.5");
292     ASSERT_EQ(0, status) << oskar_get_error_string(status);
293 
294     // Check contents.
295     const double2* a_ = oskar_mem_double2_const(a, &status);
296     const double* b_ = oskar_mem_double_const(b, &status);
297     const double* c_ = oskar_mem_double_const(c, &status);
298     for (int i = 0; i < num_elements; ++i)
299     {
300         ASSERT_NEAR(a_[i].x, i * 1.0, 1e-10);
301         ASSERT_NEAR(a_[i].y, i * 10.0, 1e-10);
302         ASSERT_NEAR(b_[i], 5.1, 1e-10);
303         ASSERT_NEAR(c_[i], 2.5, 1e-10);
304     }
305 
306     oskar_mem_free(a, &status);
307     oskar_mem_free(b, &status);
308     oskar_mem_free(c, &status);
309 
310     remove(filename);
311 }
312 
TEST(Mem,load_ascii_lots_of_columns)313 TEST(Mem, load_ascii_lots_of_columns)
314 {
315     int status = 0;
316 
317     // Write a test file.
318     const char* filename = "temp_test_load_ascii_lots_of_columns.txt";
319     FILE* file = fopen(filename, "w");
320     ASSERT_TRUE(file != NULL);
321     int num_elements = 119;
322     for (int i = 0; i < num_elements; ++i)
323     {
324         fprintf(file, "%.3f %.3f %.3f, %.3f, %.3f\n", i * 1.0, i * 10.0,
325                 i * 20.0, i * 23.0, i * 25.5);
326     }
327     fclose(file);
328 
329     // Load some columns back into CPU memory.
330     oskar_Mem *a = 0, *b = 0, *c = 0;
331     a = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU, 0, &status);
332     b = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
333     c = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
334     ASSERT_EQ(0, status) << oskar_get_error_string(status);
335 
336     // Expect pass.
337     oskar_mem_load_ascii(filename, 3, &status, a, "", b, "", c, "");
338     ASSERT_EQ(0, status) << oskar_get_error_string(status);
339 
340     // Check contents.
341     const double2* a_ = oskar_mem_double2_const(a, &status);
342     const double* b_ = oskar_mem_double_const(b, &status);
343     const double* c_ = oskar_mem_double_const(c, &status);
344     for (int i = 0; i < num_elements; ++i)
345     {
346         ASSERT_NEAR(a_[i].x, i * 1.0, 1e-10);
347         ASSERT_NEAR(a_[i].y, i * 10.0, 1e-10);
348         ASSERT_NEAR(b_[i], i * 20.0, 1e-10);
349         ASSERT_NEAR(c_[i], i * 23.0, 1e-10);
350     }
351 
352     oskar_mem_free(a, &status);
353     oskar_mem_free(b, &status);
354     oskar_mem_free(c, &status);
355 
356     remove(filename);
357 }
358 
TEST(Mem,load_ascii_required_data)359 TEST(Mem, load_ascii_required_data)
360 {
361     int status = 0;
362 
363     // Write a test file.
364     const char* filename = "temp_test_load_ascii_required_data.txt";
365     FILE* file = fopen(filename, "w");
366     ASSERT_TRUE(file != NULL);
367     int num_elements = 119;
368     for (int i = 0; i < num_elements; ++i)
369     {
370         fprintf(file, "%.3f %.3f %.3f, %.3f, %.3f\n", i * 1.0, i * 10.0,
371                 i * 20.0, i * 23.0, i * 25.5);
372     }
373     fprintf(file, "%.3f\n", 123456.789); // Write a line without enough columns.
374     fprintf(file, "%.3f %.3f\n", 11.1, 22.2); // This one should be OK.
375     for (int i = 0; i < num_elements; ++i)
376     {
377         fprintf(file, "%.3f %.3f %.3f, %.3f, %.3f\n", i * 1.0, i * 10.0,
378                 i * 20.0, i * 23.0, i * 25.5);
379     }
380     fclose(file);
381 
382     // Load some columns back into CPU memory.
383     oskar_Mem *a = 0, *b = 0, *c = 0;
384     a = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
385     b = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
386     c = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, 0, &status);
387     ASSERT_EQ(0, status) << oskar_get_error_string(status);
388 
389     // Expect pass.
390     oskar_mem_load_ascii(filename, 3, &status, a, "", b, "", c, "3.3");
391     ASSERT_EQ(0, status) << oskar_get_error_string(status);
392 
393     // Check arrays are the right length.
394     EXPECT_EQ(2 * num_elements + 1, (int)oskar_mem_length(a));
395     EXPECT_EQ(2 * num_elements + 1, (int)oskar_mem_length(b));
396     EXPECT_EQ(2 * num_elements + 1, (int)oskar_mem_length(c));
397 
398     // Check contents.
399     const double* a_ = oskar_mem_double_const(a, &status);
400     const double* b_ = oskar_mem_double_const(b, &status);
401     const double* c_ = oskar_mem_double_const(c, &status);
402     // a_[i] must always be less than 10000, because no default was
403     // supplied for b where that value was set for a.
404     for (int i = 0; i < num_elements; ++i)
405     {
406         ASSERT_NEAR(a_[i], i * 1.0, 1e-10);
407         ASSERT_LT(a_[i], 10000.0);
408         ASSERT_NEAR(b_[i], i * 10.0, 1e-10);
409         ASSERT_NEAR(c_[i], i * 20.0, 1e-10);
410     }
411     ASSERT_EQ(11.1, a_[num_elements]);
412     ASSERT_EQ(22.2, b_[num_elements]);
413     ASSERT_EQ(3.3,  c_[num_elements]);
414     for (int i = 0; i < num_elements; ++i)
415     {
416         int j = i + num_elements + 1;
417         ASSERT_NEAR(a_[j], i * 1.0, 1e-10);
418         ASSERT_LT(a_[j], 10000.0);
419         ASSERT_NEAR(b_[j], i * 10.0, 1e-10);
420         ASSERT_NEAR(c_[j], i * 20.0, 1e-10);
421     }
422 
423     oskar_mem_free(a, &status);
424     oskar_mem_free(b, &status);
425     oskar_mem_free(c, &status);
426 
427     remove(filename);
428 }
429 
430 
TEST(Mem,save_ascii)431 TEST(Mem, save_ascii)
432 {
433     int status = 0, location = OSKAR_CPU;
434     oskar_Mem *mem1 = 0, *mem2 = 0, *mem3 = 0, *mem4 = 0, *mem5 = 0, *mem6 = 0, *mem7 = 0, *mem8 = 0;
435     size_t length = 100;
436 #ifdef OSKAR_HAVE_CUDA
437     location = OSKAR_GPU;
438 #endif
439     mem1 = oskar_mem_create(OSKAR_SINGLE, OSKAR_CPU, length, &status);
440     mem2 = oskar_mem_create(OSKAR_DOUBLE, OSKAR_CPU, length, &status);
441     mem3 = oskar_mem_create(OSKAR_SINGLE_COMPLEX, OSKAR_CPU, length, &status);
442     mem4 = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, OSKAR_CPU, length, &status);
443     mem5 = oskar_mem_create(OSKAR_SINGLE, location, length, &status);
444     mem6 = oskar_mem_create(OSKAR_DOUBLE, location, length, &status);
445     mem7 = oskar_mem_create(OSKAR_SINGLE_COMPLEX, location, length, &status);
446     mem8 = oskar_mem_create(OSKAR_DOUBLE_COMPLEX, location, length, &status);
447     ASSERT_EQ(0, status) << oskar_get_error_string(status);
448 
449     oskar_mem_set_value_real(mem1, 1.0, 0, length, &status);
450     oskar_mem_set_value_real(mem2, 2.0, 0, length, &status);
451     oskar_mem_set_value_real(mem3, 3.0, 0, length, &status);
452     oskar_mem_set_value_real(mem4, 4.0, 0, length, &status);
453     oskar_mem_set_value_real(mem5, 5.0, 0, length, &status);
454     oskar_mem_set_value_real(mem6, 6.0, 0, length, &status);
455     oskar_mem_set_value_real(mem7, 7.0, 0, length, &status);
456     oskar_mem_set_value_real(mem8, 8.0, 0, length, &status);
457 
458     const char* fname = "temp_test_save_ascii.txt";
459     FILE* f = fopen(fname, "w");
460     ASSERT_TRUE(f != NULL);
461     oskar_mem_save_ascii(f, 8, 0, length, &status,
462             mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8);
463     fclose(f);
464     ASSERT_EQ(0, status) << oskar_get_error_string(status);
465 
466     oskar_mem_free(mem1, &status);
467     oskar_mem_free(mem2, &status);
468     oskar_mem_free(mem3, &status);
469     oskar_mem_free(mem4, &status);
470     oskar_mem_free(mem5, &status);
471     oskar_mem_free(mem6, &status);
472     oskar_mem_free(mem7, &status);
473     oskar_mem_free(mem8, &status);
474     ASSERT_EQ(0, status) << oskar_get_error_string(status);
475     remove(fname);
476 }
477