Project Ne10
An Open Optimized Software Library Project for the ARM Architecture
unit_test_common.c
1 /*
2  * Copyright 2012-15 ARM Limited and Contributors.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of ARM Limited nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY ARM LIMITED AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL ARM LIMITED AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * NE10 Library : test/src/unit_test_common.c
30  */
31 
32 #include<time.h>
33 #include<unistd.h>
34 #include "unit_test_common.h"
35 
36 void FILL_FLOAT_ARRAY (ne10_float32_t *arr, ne10_uint32_t count)
37 {
38  ne10_uint32_t i = 0;
39 
40  sleep (1);
41 
42  NE10_float_rng_init (time (NULL));
43 
44  for (i = 0; i < count; i++)
45  {
46  arr[i] = NE10_float_rng_next();
47  }
48 }
49 
50 void FILL_FLOAT_ARRAY_LIMIT (ne10_float32_t *arr, ne10_uint32_t count)
51 {
52  ne10_uint32_t i = 0;
53 
54  sleep (1);
55 
56  NE10_float_rng_limit_init (time (NULL));
57 
58  for (i = 0; i < count; i++)
59  {
60  arr[ i ] = NE10_float_rng_limit_next();
61  }
62 }
63 
64 void FILL_FLOAT_ARRAY_LIMIT_GT1 (ne10_float32_t *arr, ne10_uint32_t count)
65 {
66  ne10_uint32_t i = 0;
67 
68  sleep (1);
69 
70  NE10_float_rng_limit_gt1_init (time (NULL));
71 
72  for (i = 0; i < count; i++)
73  {
74  arr[ i ] = NE10_float_rng_limit_gt1_next();
75  }
76 }
77 
78 // this function checks whether the difference between two ne10_float32_t values is within the acceptable error range
79 ne10_int32_t EQUALS_FLOAT (ne10_float32_t fa, ne10_float32_t fb , ne10_uint32_t err)
80 { ne10_float32_t tolerance = (ne10_float32_t)err / 200000;
81  if (abs(fa-fb) <= tolerance)
82  {
83  return 1;
84  }
85  else
86  {
87  return 0;
88  }
89 }
90 
91 ne10_float32_t ARRAY_GUARD_SIG[ARRAY_GUARD_LEN] = { 10.0f, 20.0f, 30.0f, 40.0f };
92 // this function adds a ARRAY_GUARD_LEN signature to the begining and the end of an array, minimum acceptable size for the array is 2*ARRAY_GUARD_LEN.
93 ne10_int32_t GUARD_ARRAY (ne10_float32_t* array, ne10_uint32_t array_length)
94 {
95  ne10_float32_t* the_array = array - ARRAY_GUARD_LEN;
96  memcpy (the_array, ARRAY_GUARD_SIG, sizeof (ARRAY_GUARD_SIG));
97  the_array = array + array_length;
98  memcpy (the_array, ARRAY_GUARD_SIG, sizeof (ARRAY_GUARD_SIG));
99  return 1;
100 }
101 
102 // this function returns TRUE if the signature matches the ARRAY_GUARD_SIGguard and returns FALSE otherwise
103 ne10_int32_t CHECK_ARRAY_GUARD (ne10_float32_t* array, ne10_uint32_t array_length)
104 {
105  ne10_float32_t* the_array = array - ARRAY_GUARD_LEN;
106  ne10_int32_t i;
107  for (i = 0; i < ARRAY_GUARD_LEN; i++)
108  {
109  if (! EQUALS_FLOAT (the_array[i], ARRAY_GUARD_SIG[i], ERROR_MARGIN_SMALL))
110  {
111  fprintf (stderr, " ERROR: prefix array guard signature is wrong. \n");
112  return 0; // Match not found, return FALSE
113  }
114  }
115 
116  the_array = array + array_length;
117  for (i = 0; i < ARRAY_GUARD_LEN; i++)
118  {
119  if (! EQUALS_FLOAT (the_array[i], ARRAY_GUARD_SIG[i], ERROR_MARGIN_SMALL))
120  {
121  fprintf (stderr, " ERROR: suffix array guard signature is wrong. \n");
122  return 0; // Match not found, return FALSE
123  }
124  }
125 
126  return 1;
127 }
128 
129 
130 ne10_uint8_t ARRAY_GUARD_SIG_UINT8[ARRAY_GUARD_LEN] = { 0x12, 0x34, 0x56, 0x78 };
131 // this function adds a ARRAY_GUARD_LEN signature to the begining and the end of an array, minimum acceptable size for the array is 2*ARRAY_GUARD_LEN.
132 ne10_int32_t GUARD_ARRAY_UINT8 (ne10_uint8_t* array, ne10_uint32_t array_length)
133 {
134  ne10_uint8_t* the_array = array - ARRAY_GUARD_LEN;
135  memcpy (the_array, ARRAY_GUARD_SIG_UINT8, sizeof (ARRAY_GUARD_SIG_UINT8));
136  the_array = array + array_length;
137  memcpy (the_array, ARRAY_GUARD_SIG_UINT8, sizeof (ARRAY_GUARD_SIG_UINT8));
138  return 1;
139 }
140 
141 // this function returns TRUE if the signature matches the ARRAY_GUARD_SIGguard and returns FALSE otherwise
142 ne10_int32_t CHECK_ARRAY_GUARD_UINT8 (ne10_uint8_t* array, ne10_uint32_t array_length)
143 {
144  ne10_uint8_t* the_array = array - ARRAY_GUARD_LEN;
145  ne10_int32_t i;
146  for (i = 0; i < ARRAY_GUARD_LEN; i++)
147  {
148  if (the_array[i] != ARRAY_GUARD_SIG_UINT8[i])
149  {
150  fprintf (stderr, " ERROR: prefix array guard signature is wrong. \n");
151  return 0; // Match not found, return FALSE
152  }
153  }
154 
155  the_array = array + array_length;
156  for (i = 0; i < ARRAY_GUARD_LEN; i++)
157  {
158  if (the_array[i] != ARRAY_GUARD_SIG_UINT8[i])
159  {
160  fprintf (stderr, " ERROR: suffix array guard signature is wrong. \n");
161  return 0; // Match not found, return FALSE
162  }
163  }
164 
165  return 1;
166 }
167 
178 ne10_float32_t CAL_SNR_FLOAT32 (ne10_float32_t *pRef, ne10_float32_t *pTest, ne10_uint32_t buffSize)
179 {
180  ne10_float32_t EnergySignal = 0.0, EnergyError = 0.0;
181  ne10_uint32_t i;
182  ne10_float32_t SNR;
183 
184  for (i = 0; i < buffSize; i++)
185  {
186  EnergySignal += pRef[i] * pRef[i];
187  EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
188  }
189  SNR = 10 * log10 (EnergySignal / EnergyError);
190  return (SNR);
191 
192 }
193 
204 ne10_float32_t CAL_PSNR_UINT8 (ne10_uint8_t *pRef, ne10_uint8_t *pTest, ne10_uint32_t buffSize)
205 {
206  ne10_float64_t mse = 0.0, max = 255.0;
207  ne10_uint32_t i;
208  ne10_float32_t PSNR;
209 
210  for (i = 0; i < buffSize; i++)
211  {
212  mse += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
213  }
214  mse /= buffSize;
215  PSNR = 10 * log10 (max*max / mse);
216  return (PSNR);
217 
218 }
219 char ne10_log_buffer[5000];
220 char *ne10_log_buffer_ptr;
221 
222 void ne10_log(const char *func_name,
223  const char *format_str,
224  ne10_int32_t n,
225  ne10_int32_t time_c,
226  ne10_int32_t time_neon,
227  ne10_float32_t time_savings,
228  ne10_float32_t time_speedup)
229 {
230  int byte_count = 0;
231  byte_count = sprintf(ne10_log_buffer_ptr,
232  "{ \"name\" : \"%s %d\", \"time_c\" : %d, "
233  "\"time_neon\" : %d },",
234  func_name, n, time_c, time_neon);
235  ne10_log_buffer_ptr += byte_count;
236 
237  /* print the result, which is needed by command line performance test. */
238  fprintf (stdout,
239  "%25d%20d%20d%19.2f%%%18.2f:1\n",
240  n,
241  time_c,
242  time_neon,
243  time_savings,
244  time_speedup);
245 }
246 
247 /* this function should handle all performance result output. ne10_log
248  * should be replaced by this function.
249  * info parameter contains the misc information, which is in below format:
250  * key1:value1\nkey2:value2\nkey3:value3
251  */
252 void ne10_performance_print(ne10_print_target_t target,
253  long int neon_ticks,
254  long int c_ticks,
255  char *info)
256 {
257  double f = (double)c_ticks / neon_ticks;
258  switch (target) {
259  case UBUNTU_COMMAND_LINE:
260  printf("\n%s\nneon(ms): %.2f c(ms): %.2f(ms) speedup: %.2f",
261  info,
262  neon_ticks / 1000.0,
263  c_ticks / 1000.0,
264  f);
265  break;
266  case ANDROID_DEMO:
267  break;
268  case IOS_DEMO:
269  break;
270  }
271 }
272 
273 void diff(const ne10_uint8_t *mat1,
274  const ne10_uint8_t *mat2,
275  ne10_int32_t *dst,
276  ne10_uint32_t dst_stride,
277  ne10_uint32_t width,
278  ne10_uint32_t height,
279  ne10_uint32_t src_stride,
280  ne10_uint32_t channel)
281 {
282  assert(mat1 != 0 && mat2 != 0 && dst != 0);
283 
284  int i, j, k;
285 
286  for(k = 0; k < channel; k++)
287  {
288  for(j = 0; j < height; j++)
289  {
290  const ne10_uint8_t *row1 = mat1 + j * src_stride;
291  const ne10_uint8_t *row2 = mat2 + j * src_stride;
292  ne10_int32_t *row_dst = dst + j * dst_stride / sizeof(ne10_int32_t);
293  for(i = 0; i < width; i++)
294  {
295  *(row_dst + i * channel + k) =
296  (ne10_int32_t) (*(row1 + i * channel + k)) -
297  *(row2 + i * channel + k);
298  }
299  }
300  }
301 }
302 
303 /* check how many point is not in [-2, 2] */
304 int diff_count(const ne10_int32_t *mat,
305  ne10_int32_t width,
306  ne10_int32_t height,
307  ne10_int32_t stride,
308  ne10_int32_t channel)
309 {
310  assert(mat != 0);
311 
312  int i, j, k;
313  int count = 0;
314  for(j = 0; j < height; j++)
315  {
316  const ne10_int32_t *row = mat + j * stride / sizeof(ne10_int32_t);
317  for(i = 0; i < width; i++)
318  {
319  for(k = 0; k < channel; k++)
320  {
321  const ne10_int32_t val = *(row + i * channel + k);
322  if (val != -1 && val != 0 && val != -2 && val != 1 && val != 2)
323  {
324  ++count;
325  }
326  }
327  }
328  }
329 
330  return count;
331 }
332 
333 void progress_bar(float progress)
334 {
335  assert(progress <= 1);
336 
337  static float progress_prev = 0;
338  if (progress != progress_prev)
339  {
340  int bar_width = 70;
341 
342  printf("[");
343  int pos = bar_width * progress;
344  int i;
345  for (i = 0; i < bar_width; ++i) {
346  if (i < pos)
347  printf("=");
348  else if (i == pos)
349  printf(">");
350  else
351  printf(" ");
352  }
353  printf("] %d%%\r", (int)(progress * 100.0));
354  fflush(stdout);
355  progress_prev = progress;
356  }
357 }