1 /*********************************************************************
2   Blosc - Blocked Shuffling and Compression Library
3 
4   Roundtrip tests for the ALTIVEC-accelerated shuffle/unshuffle.
5 
6   Copyright (C) 2021  The Blosc Developers <blosc@blosc.org>
7   https://blosc.org
8   License: BSD 3-Clause (see LICENSE.txt)
9 
10   See LICENSE.txt for details about copyright and rights to use.
11 **********************************************************************/
12 
13 #include "test_common.h"
14 #include "../blosc/shuffle.h"
15 #include "../blosc/shuffle-generic.h"
16 
17 
18 /* Include ALTIVEC-accelerated shuffle implementation if supported by this compiler.
19    TODO: Need to also do run-time CPU feature support here. */
20 #if defined(SHUFFLE_ALTIVEC_ENABLED)
21   #include "../blosc/shuffle-altivec.h"
22 #else
23   #if defined(_MSC_VER)
24     #pragma message("ALTIVEC shuffle tests not enabled.")
25   #else
26     #warning ALTIVEC shuffle tests not enabled.
27   #endif
28 #endif  /* defined(SHUFFLE_ALTIVEC_ENABLED) */
29 
30 
31 /** Roundtrip tests for the ALTIVEC-accelerated shuffle/unshuffle. */
test_shuffle_roundtrip_altivec(int32_t type_size,int32_t num_elements,size_t buffer_alignment,int test_type)32 static int test_shuffle_roundtrip_altivec(int32_t type_size, int32_t num_elements,
33                                           size_t buffer_alignment, int test_type) {
34 #if defined(SHUFFLE_ALTIVEC_ENABLED)
35   int32_t buffer_size = type_size * num_elements;
36 
37   /* Allocate memory for the test. */
38   void* original = blosc_test_malloc(buffer_alignment, (size_t)buffer_size);
39   void* shuffled = blosc_test_malloc(buffer_alignment, (size_t)buffer_size);
40   void* unshuffled = blosc_test_malloc(buffer_alignment, (size_t)buffer_size);
41 
42   /* Fill the input data buffer with random values. */
43   blosc_test_fill_seq(original, (size_t)buffer_size);
44 
45   /* Shuffle/unshuffle, selecting the implementations based on the test type. */
46   switch (test_type) {
47     case 0:
48       /* altivec/altivec */
49       shuffle_altivec(type_size, buffer_size, original, shuffled);
50       unshuffle_altivec(type_size, buffer_size, shuffled, unshuffled);
51       break;
52     case 1:
53       /* generic/altivec */
54       shuffle_generic(type_size, buffer_size, original, shuffled);
55       unshuffle_altivec(type_size, buffer_size, shuffled, unshuffled);
56       break;
57     case 2:
58       /* altivec/generic */
59       shuffle_altivec(type_size, buffer_size, original, shuffled);
60       unshuffle_generic(type_size, buffer_size, shuffled, unshuffled);
61       break;
62     default:
63       fprintf(stderr, "Invalid test type specified (%d).", test_type);
64       return EXIT_FAILURE;
65   }
66 
67   /* The round-tripped data matches the original data when the
68      result of memcmp is 0. */
69   int exit_code = memcmp(original, unshuffled, (size_t)buffer_size) ?
70                   EXIT_FAILURE : EXIT_SUCCESS;
71 
72   /* Free allocated memory. */
73   blosc_test_free(original);
74   blosc_test_free(shuffled);
75   blosc_test_free(unshuffled);
76 
77   return exit_code;
78 #else
79   return EXIT_SUCCESS;
80 #endif /* defined(SHUFFLE_ALTIVEC_ENABLED) */
81 }
82 
83 
84 /** Required number of arguments to this test, including the executable name. */
85 #define TEST_ARG_COUNT  5
86 
main(int argc,char ** argv)87 int main(int argc, char** argv) {
88   /*  argv[1]: sizeof(element type)
89       argv[2]: number of elements
90       argv[3]: buffer alignment
91       argv[4]: test type
92   */
93 
94   /*  Verify the correct number of command-line args have been specified. */
95   if (TEST_ARG_COUNT != argc) {
96     blosc_test_print_bad_argcount_msg(TEST_ARG_COUNT, argc);
97     return EXIT_FAILURE;
98   }
99 
100   /* Parse arguments */
101   uint32_t type_size;
102   if (!blosc_test_parse_uint32_t(argv[1], &type_size) || (type_size < 1)) {
103     blosc_test_print_bad_arg_msg(1);
104     return EXIT_FAILURE;
105   }
106 
107   uint32_t num_elements;
108   if (!blosc_test_parse_uint32_t(argv[2], &num_elements) || (num_elements < 1)) {
109     blosc_test_print_bad_arg_msg(2);
110     return EXIT_FAILURE;
111   }
112 
113   uint32_t buffer_align_size;
114   if (!blosc_test_parse_uint32_t(argv[3], &buffer_align_size)
115       || (buffer_align_size & (buffer_align_size - 1))
116       || (buffer_align_size < sizeof(void*))) {
117     blosc_test_print_bad_arg_msg(3);
118     return EXIT_FAILURE;
119   }
120 
121   uint32_t test_type;
122   if (!blosc_test_parse_uint32_t(argv[4], &test_type) || (test_type > 2)) {
123     blosc_test_print_bad_arg_msg(4);
124     return EXIT_FAILURE;
125   }
126 
127   /* Run the test. */
128   return test_shuffle_roundtrip_altivec(type_size, num_elements, buffer_align_size, test_type);
129 }
130