Adding missing header file
authorDavid Butcher <dbutcher@arm.com>
Wed, 11 Apr 2012 11:42:13 +0000 (12:42 +0100)
committerDavid Butcher <dbutcher@arm.com>
Wed, 11 Apr 2012 11:42:13 +0000 (12:42 +0100)
headers/unit_test_x_operation_x_tolerant.h [new file with mode: 0644]

diff --git a/headers/unit_test_x_operation_x_tolerant.h b/headers/unit_test_x_operation_x_tolerant.h
new file mode 100644 (file)
index 0000000..5aa19b1
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ *  Copyright 2011-12 ARM Limited
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/*
+ * NE10 Library : headers/unit_test_x_operation_x.h
+ */
+
+#include "./unit_test_common.h"
+
+// This function signature applies the operations with the format "*c_*_*" (e.g. 'add'c_'float'_'neon')
+typedef arm_result_t (*arm_func_4args_t)(void * dst, void * src1, void * src2, unsigned int count);
+arm_func_4args_t ftbl[ OP_COUNT * IMPL_COUNT ];
+
+
+// this function is implemented in the unit test source files
+// it is meant to initialise the function table defined above.
+extern void init_ftbl();
+
+
+unsigned int i = 0;   // loop iterator
+unsigned int max = 0; // number of iterations in each function
+int opcode = -1; // the operation which will be tested (a single unit can have any number of operations/functions)
+int impl   = -1; // selects which particular implementation of the chosen operation must run
+int mute   = 0;   // 0 == print output;   1 == do not print anything;
+
+struct timeval  before, after, lapsed, dummy;
+double dt_test_overhead = 0.0;
+double dt_test_sample = 0.0;
+double elapsed = 0.0;
+struct timezone zone;
+
+// there is a max of "4" components in a vec
+#define MAX_VEC_COMPONENTS 4
+
+arm_float_t * thesrc1 = NULL;
+arm_float_t * thesrc2 = NULL;
+arm_float_t * thedst[IMPL_COUNT]; // output from different implementations are stored in separate arrays for varification
+int done_init = 0;
+
+arm_result_t test_operation()
+{
+  // initialize if not done so
+  if ( 0 == done_init )
+  {
+    thesrc1 = (arm_float_t*) malloc( ARRLEN * sizeof(arm_float_t) * MAX_VEC_COMPONENTS );
+    FILL_FLOAT_ARRAY_LIMIT( thesrc1, ARRLEN * MAX_VEC_COMPONENTS ); // random initialization
+
+    thesrc2 = (arm_float_t*) malloc( ARRLEN * sizeof(arm_float_t) * MAX_VEC_COMPONENTS );
+    FILL_FLOAT_ARRAY_LIMIT( thesrc2, ARRLEN * MAX_VEC_COMPONENTS ); // random initialization
+
+    for ( i = 0; i<IMPL_COUNT; i++ )
+    {
+      thedst[i] = (arm_float_t*) malloc( ARRLEN * sizeof(arm_float_t) * MAX_VEC_COMPONENTS );
+    }
+
+    done_init = 1;
+  }
+
+  // sample run
+  MEASURE( dt_test_sample,
+    ftbl [ FTBL_IDX(opcode, impl) ] ( thedst[ impl-1 ] , thesrc1, thesrc2, ARRLEN );
+  );
+
+          MEASURE( elapsed,
+            for ( i = 0; i < max; i++  )
+            {
+               // call the function
+               ftbl [ FTBL_IDX(opcode, impl) ] ( thedst[ impl -1 ] , thesrc1, thesrc2, ARRLEN );
+            }
+           );
+
+  if ( !mute )
+       printf( "%02.8f;%013.3f\n", elapsed - dt_test_overhead,
+                              ( 1.0f * max * ARRLEN / ( elapsed - dt_test_overhead ))  );
+
+ return NE10_OK;
+}
+
+arm_result_t run_test( int argc, char **argv )
+{
+   if ( argc == 2 ) // requesting the number of available operations/routines in this unit
+   {
+      opcode = atoi ( argv[1] ); // get the command being requested, 0 = return the number of functions in this unit
+      if ( opcode == 0 ) return OP_COUNT;
+      exit( NE10_ERR );
+   } else if ( argc == 4 ) // requesting a particular implementation of one of the operations
+   {
+      opcode = atoi ( argv[1] );
+      if ( opcode <= 0 ) exit( NE10_ERR );
+      impl   = atoi ( argv[2] );
+      if ( impl   < 0 ) exit( NE10_ERR ); // impl == 0 means run all and compare the results to verify they produce identical outputs
+      max = atoi ( argv[3] );
+      if ( max <= 0 ) exit( NE10_ERR );
+   } else exit( NE10_ERR );
+
+   // initialize the table with NULL
+   memset( ftbl, 0, sizeof(ftbl));
+
+   // manually initialize the functions which have actual implementations
+   init_ftbl(); // this function is implemented in the unit test source file
+
+  if ( opcode <= 0 || opcode > OP_COUNT
+       || impl < 0 || impl > IMPL_COUNT )
+  {
+      fprintf ( stderr, "\t WARNING: Operation number %d and/or implementaion number %d are not acceptable values. \n", opcode, impl );
+      exit( NE10_ERR );
+  }
+
+  if ( impl == 0 ) // run all implementations and verify
+  {
+      // first, make sure all of the implementations do exist
+      for ( i = FTBL_IDX(opcode, 1); i <= FTBL_IDX(opcode, IMPL_COUNT); i++ )
+      {
+        if ( NULL == ftbl[i] )
+        {
+                fprintf ( stderr, "\t WARNING: One or more implementations of operation number %d were not found. \n", opcode );
+                exit( NE10_ERR );
+        }
+      }
+
+      // try all the implementatins here..
+             mute = 1; // do not print anything
+
+             // opcode remains the same but we iterate through different implementations here..
+             for ( impl= 1; impl <= IMPL_COUNT; impl ++ )
+             {
+                 test_operation();
+             }
+
+             // now verify
+             arm_float_t * _output = NULL; // [ IMPL_COUNT * MAX_VEC_COMPONENTS ]; // one for each implementation, c, asm, neon...
+             int warns = 0;
+             int item_width = opcode; // there's no easy way to guess the actual number of an item's components but using the opcode (1=float, 2=vec2, ...)
+             _output = (arm_float_t*) malloc( IMPL_COUNT * sizeof(arm_float_t) * item_width );
+             for ( i = 0; i < ARRLEN; i++ )
+             {
+                 for ( impl= 1; impl <= IMPL_COUNT; impl ++ )
+                 {
+                     memcpy ( &_output[  (impl-1) * item_width  ], &thedst[ impl-1 ][ i * item_width ],  sizeof(arm_float_t) * item_width  );
+                 }
+
+                 int pos = 0;
+                 for ( impl = 2; impl <= IMPL_COUNT; impl ++ ) // compare the output from the 2nd, 3rd, 4th, etc. to the first one so start at 2
+                 {
+                     for ( pos = 0; pos < item_width; pos++ ) // compare corresponding components of the items
+                     {
+                         assert ( _output[ ((1-1)*item_width)+pos ] == _output[ ((1-1)*item_width)+pos ] ); // check for not-a-number
+                         assert ( _output[ ((impl-1)*item_width)+pos ] == _output[ ((impl-1)*item_width)+pos ] );  // check for not-a-number
+
+                         if ( ! EQUALS_FLOAT( _output[ ((1-1)*item_width)+pos ] , _output[ ((impl-1)*item_width)+pos ], ERROR_MARGIN_LARGE ) ) // accept larger errors
+                         { fprintf( stderr, "\t\t WARNING: In opcode [%d], implementation [1] != implemenation [%d] on item [%d -> %d]\n",
+                                    opcode, impl, i, pos+1 );
+                             warns++; }
+
+                         // stop after 10 warnings
+                         if ( warns >= ACCEPTABLE_WARNS )
+                         {    fprintf ( stderr, "\t WARNING: One or more mismatching values were found. \n" );
+                              exit( NE10_ERR );
+                         }
+                     }
+                 }
+             }
+             free( _output ); _output = (arm_float_t *) NULL;
+
+             if ( 0 == warns )
+             {
+               return NE10_OK;
+             }
+
+             fprintf ( stderr, "\t WARNING: One or more mismatching values were found. \n" );
+             exit( NE10_ERR );
+  }
+  else // run a particular implementation
+  {
+      if ( !mute ) printf( "opcode=%d;impl=%d;%d;%d;", opcode, impl, ARRLEN, max );
+
+      // ge the overhead
+      MEASURE( dt_test_overhead,
+               for ( i = 0 ; i < max; i++ )
+               {
+               }
+              );
+
+       test_operation();
+  }
+
+
+
+  // free any allocated memory...
+  free( thesrc1 );
+  free( thesrc2 );
+  for ( i = 0; i<IMPL_COUNT; i++ )
+  {
+    free( thedst[i] );
+  }
+
+  return NE10_OK;
+}