text: /*M///////////////////////////////////////////////////////////////////////////////////////
  //
  //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  //
  //  By downloading, copying, installing or using the software you agree to this license.
  //  If you do not agree to this license, do not download, install,
  //  copy or use the software.
  //
  //
  //                        Intel License Agreement
  //                For Open Source Computer Vision Library
  //
  // Copyright (C) 2000, Intel Corporation, all rights reserved.
  // Third party copyrights are property of their respective owners.
  //
  // Redistribution and use in source and binary forms, with or without modification,
  // are permitted provided that the following conditions are met:
  //
  //   * Redistribution's of source code must retain the above copyright notice,
  //     this list of conditions and the following disclaimer.
  //
  //   * Redistribution's in binary form must reproduce the above copyright notice,
  //     this list of conditions and the following disclaimer in the documentation
  //     and/or other materials provided with the distribution.
  //
  //   * The name of Intel Corporation may not be used to endorse or promote products
  //     derived from this software without specific prior written permission.
  //
  // This software is provided by the copyright holders and contributors "as is" and
  // any express or implied warranties, including, but not limited to, the implied
  // warranties of merchantability and fitness for a particular purpose are disclaimed.
  // In no event shall the Intel Corporation or contributors be liable for any direct,
  // indirect, incidental, special, exemplary, or consequential damages
  // (including, but not limited to, procurement of substitute goods or services;
  // loss of use, data, or profits; or business interruption) however caused
  // and on any theory of liability, whether in contract, strict liability,
  // or tort (including negligence or otherwise) arising in any way out of
  // the use of this software, even if advised of the possibility of such damage.
  //
  //M*/
  
  
  /****************************************************************************************/
  /*                         Dynamic detection and loading of IPP modules                 */
  /****************************************************************************************/
  
  #include "_cxcore.h"
  
  #if defined _MSC_VER && _MSC_VER >= 1200
  #pragma warning( disable: 4115 )        /* type definition in () */
  #endif
  
  #if defined _MSC_VER && defined WIN64 && !defined EM64T
  #pragma optimize( "", off )
  #endif
  
  #if defined WIN32 || defined WIN64
  #include <windows.h>
  #else
  #include <dlfcn.h>
  #include <sys/time.h>
  #endif
  
  #include <string.h>
  #include <stdio.h>
  #include <ctype.h>
  
  #define CV_PROC_GENERIC             0
  #define CV_PROC_SHIFT               10
  #define CV_PROC_ARCH_MASK           ((1 << CV_PROC_SHIFT) - 1)
  #define CV_PROC_IA32_GENERIC        1
  #define CV_PROC_IA32_WITH_MMX       (CV_PROC_IA32_GENERIC|(2 << CV_PROC_SHIFT))
  #define CV_PROC_IA32_WITH_SSE       (CV_PROC_IA32_GENERIC|(3 << CV_PROC_SHIFT))
  #define CV_PROC_IA32_WITH_SSE2      (CV_PROC_IA32_GENERIC|(4 << CV_PROC_SHIFT))
  #define CV_PROC_IA64                2
  #define CV_PROC_EM64T               3
  #define CV_GET_PROC_ARCH(model)     ((model) & CV_PROC_ARCH_MASK)
  
  typedef struct CvProcessorInfo
  {
      int model;
      int count;
      double frequency; // clocks per microsecond
  }
  CvProcessorInfo;
  
  #undef MASM_INLINE_ASSEMBLY
  
  #if defined WIN32 && !defined  WIN64
  
  #if defined _MSC_VER
  #define MASM_INLINE_ASSEMBLY 1
  #elif defined __BORLANDC__
  
  #if __BORLANDC__ >= 0x560
  #define MASM_INLINE_ASSEMBLY 1
  #endif
  
  #endif
  
  #endif
  
  /*
     determine processor type
  */
  static void
  icvInitProcessorInfo( CvProcessorInfo* cpu_info )
  {
      memset( cpu_info, 0, sizeof(*cpu_info) );
      cpu_info->model = CV_PROC_GENERIC;
  
  #if defined WIN32 || defined WIN64
  
  #ifndef PROCESSOR_ARCHITECTURE_AMD64
  #define PROCESSOR_ARCHITECTURE_AMD64 9
  #endif
  
  #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_WIN64
  #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
  #endif
  
      SYSTEM_INFO sys;
      LARGE_INTEGER freq;
  
      GetSystemInfo( &sys );
  
      if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL &&
          sys.dwProcessorType == PROCESSOR_INTEL_PENTIUM && sys.wProcessorLevel >= 6 )
      {
          int version = 0, features = 0, family = 0;
          int id = 0;
          HKEY key = 0;
  
          cpu_info->count = (int)sys.dwNumberOfProcessors;
          unsigned long val = 0, sz = sizeof(val);
  
          if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0\\",
              0, KEY_QUERY_VALUE, &key ) >= 0 )
          {
              if( RegQueryValueEx( key, "~MHz", 0, 0, (uchar*)&val, &sz ) >= 0 )
                  cpu_info->frequency = (double)val;
              RegCloseKey( key );
          }
  
  #ifdef MASM_INLINE_ASSEMBLY
          __asm
          {
              /* use CPUID to determine the features supported */
              pushfd
              mov   eax, 1
              push  ebx
              push  esi
              push  edi
  #ifdef __BORLANDC__
              db 0fh
              db 0a2h
  #else
              _emit 0x0f
              _emit 0xa2
  #endif
              pop   edi
              pop   esi
              pop   ebx
              mov   version, eax
              mov   features, edx
              popfd
          }
  #elif defined WIN32 && __GNUC__ > 2
          asm volatile
          (
              "movl $1,%%eax\n\t"
              ".byte 0x0f; .byte 0xa2\n\t"
              "movl %%eax, %0\n\t"
              "movl %%edx, %1\n\t"
              : "=r"(version), "=r" (features)
              :
              : "%ebx", "%esi", "%edi"
          );
  #else
          {
              static const char cpuid_code[] =
                  "\x53\x56\x57\xb8\x01\x00\x00\x00\x0f\xa2\x5f\x5e\x5b\xc3";
              typedef int64 (CV_CDECL * func_ptr)(void);
              func_ptr cpuid = (func_ptr)(void*)cpuid_code;
              int64 cpuid_val = cpuid();
              version = (int)cpuid_val;
              features = (int)(cpuid_val >> 32);
          }
  #endif
  
          #define ICV_CPUID_M6     ((1<<15)|(1<<23))  /* cmov + MMX */
          #define ICV_CPUID_A6     ((1<<25)|ICV_CPUID_M6) /* <all above> + SSE */
          #define ICV_CPUID_W7     ((1<<26)|ICV_CPUID_A6) /* <all above> + SSE2 */
  
          family = (version >> 8) & 15;
          if( family >= 6 && (features & ICV_CPUID_M6) != 0 ) /* Pentium II or higher */
              id = features & ICV_CPUID_W7;
  
          cpu_info->model = id == ICV_CPUID_W7 ? CV_PROC_IA32_WITH_SSE2 :
                            id == ICV_CPUID_A6 ? CV_PROC_IA32_WITH_SSE :
                            id == ICV_CPUID_M6 ? CV_PROC_IA32_WITH_MMX :
                            CV_PROC_IA32_GENERIC;
      }
      else
      {
  #if defined EM64T
          if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 )
              cpu_info->model = CV_PROC_EM64T;
  #elif defined WIN64
          if( sys.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 )
              cpu_info->model = CV_PROC_IA64;
  #endif
          if( QueryPerformanceFrequency( &freq ) )
              cpu_info->frequency = (double)freq.QuadPart;
      }
  #else
      cpu_info->frequency = 1;
  
  #ifdef __x86_64__
      cpu_info->model = CV_PROC_EM64T;
  #elif defined __ia64__
      cpu_info->model = CV_PROC_IA64;
  #elif !defined __i386__
      cpu_info->model = CV_PROC_GENERIC;
  #else
      cpu_info->model = CV_PROC_IA32_GENERIC;
      
      // reading /proc/cpuinfo file (proc file system must be supported)
      FILE *file = fopen( "/proc/cpuinfo", "r" );
  
      if( file )
      {
          char buffer[1024];
          int max_size = sizeof(buffer)-1;
  
          for(;;)
          {
              const char* ptr = fgets( buffer, max_size, file );
              if( !ptr )
                  break;
              if( strncmp( buffer, "flags", 5 ) == 0 )
              {
                  if( strstr( buffer, "mmx" ) && strstr( buffer, "cmov" ))
                  {
                      cpu_info->model = CV_PROC_IA32_WITH_MMX;
                      if( strstr( buffer, "xmm" ) || strstr( buffer, "sse" ))
                      {
                          cpu_info->model = CV_PROC_IA32_WITH_SSE;
                          if( strstr( buffer, "emm" ))
                              cpu_info->model = CV_PROC_IA32_WITH_SSE2;
                      }
                  }
              }
              else if( strncmp( buffer, "cpu MHz", 7 ) == 0 )
              {
                  char* pos = strchr( buffer, ':' );
                  if( pos )
                      cpu_info->frequency = strtod( pos + 1, &pos );
              }
          }
  
          fclose( file );
          if( CV_GET_PROC_ARCH(cpu_info->model) != CV_PROC_IA32_GENERIC )
              cpu_info->frequency = 1;
          else
              assert( cpu_info->frequency > 1 );
      }
  #endif
  #endif
  }
  
  
  CV_INLINE const CvProcessorInfo*
  icvGetProcessorInfo()
  {
      static CvProcessorInfo cpu_info;
      static int init_cpu_info = 0;
      if( !init_cpu_info )
      {
          icvInitProcessorInfo( &cpu_info );
          init_cpu_info = 1;
      }
      return &cpu_info;
  }
  
  
  /****************************************************************************************/
  /*                               Make functions descriptions                            */
  /****************************************************************************************/
  
  #undef IPCVAPI_EX
  #define IPCVAPI_EX(type,func_name,names,modules,arg) \
      { (void**)&func_name##_p, (void*)(size_t)-1, names, modules, 0 },
  
  #undef IPCVAPI_C_EX
  #define IPCVAPI_C_EX(type,func_name,names,modules,arg) \
      { (void**)&func_name##_p, (void*)(size_t)-1, names, modules, 0 },
  
  static CvPluginFuncInfo cxcore_ipp_tab[] =
  {
  #undef _CXCORE_IPP_H_
  #include "_cxipp.h"
  #undef _CXCORE_IPP_H_
      {0, 0, 0, 0, 0}
  };
  
  
  /*
     determine processor type, load appropriate dll and
     initialize all function pointers
  */
  #if defined WIN32 || defined WIN64
  #define DLL_PREFIX ""
  #define DLL_SUFFIX ".dll"
  #else
  #define DLL_PREFIX "lib"
  #define DLL_SUFFIX ".so"
  #define LoadLibrary(name) dlopen(name, RTLD_LAZY)
  #define FreeLibrary(name) dlclose(name)
  #define GetProcAddress dlsym
  typedef void* HMODULE;
  #endif
  
  #if 0 /*def _DEBUG*/
  #define DLL_DEBUG_FLAG "d"
  #else
  #define DLL_DEBUG_FLAG ""
  #endif
  
  #define VERBOSE_LOADING 0
  
  #if VERBOSE_LOADING
  #define ICV_PRINTF(args)  printf args; fflush(stdout)
  #else
  #define ICV_PRINTF(args)
  #endif
  
  typedef struct CvPluginInfo
  {
      const char* basename;
      HMODULE handle;
      char name[100];
  }
  CvPluginInfo;
  
  static CvPluginInfo plugins[CV_PLUGIN_MAX];
  static CvModuleInfo cxcore_info = { 0, "cxcore", CV_VERSION, cxcore_ipp_tab };
  
  CvModuleInfo *CvModule::first = 0, *CvModule::last = 0;
  
  CvModule::CvModule( CvModuleInfo* _info )
  {
      cvRegisterModule( _info );
      info = last;
  }
  
  CvModule::~CvModule()
  {
      if( info )
      {
          CvModuleInfo* p = first;
          for( ; p != 0 && p->next != info; p = p->next )
              ;
          if( p )
              p->next = info->next;
          if( first == info )
              first = info->next;
          if( last == info )
              last = p;
          cvFree( &info );
          info = 0;
      }
  }
  
  static int
  icvUpdatePluginFuncTab( CvPluginFuncInfo* func_tab )
  {
      int i, loaded_functions = 0;
  
      // 1. reset pointers
      for( i = 0; func_tab[i].func_addr != 0; i++ )
      {
          if( func_tab[i].default_func_addr == (void*)(size_t)-1 )
              func_tab[i].default_func_addr = *func_tab[i].func_addr;
          else
              *func_tab[i].func_addr = func_tab[i].default_func_addr;
          func_tab[i].loaded_from = 0;
      }
  
      // ippopencv substitutes all the other IPP modules
      if( plugins[CV_PLUGIN_OPTCV].handle != 0 )
      {
          for( i = 2; i < CV_PLUGIN_MKL; i++ )
          {
              assert( plugins[i].handle == 0 );
              plugins[i].handle = plugins[CV_PLUGIN_OPTCV].handle;
          }
      }
  
      // 2. try to find corresponding functions in ipp* and reassign pointers to them
      for( i = 0; func_tab[i].func_addr != 0; i++ )
      {
      #if defined _MSC_VER && _MSC_VER >= 1200
          #pragma warning( disable: 4054 4055 ) /* converting pointers to code<->data */
      #endif
          char name[100];
          int j = 0, idx = 0;
  
          assert( func_tab[i].loaded_from == 0 );
  
          if( func_tab[i].search_modules )
          {
              uchar* addr = 0;
              const char* name_ptr = func_tab[i].func_names;
  
              for( ; j < 10 && name_ptr; j++ )
              {
                  const char* name_start = name_ptr;
                  const char* name_end;
                  while( !isalpha(name_start[0]) && name_start[0] != '\0' )
                      name_start++;
                  if( !name_start[0] )
                      name_start = 0;
                  name_end = name_start ? strchr( name_start, ',' ) : 0;
                  idx = (func_tab[i].search_modules / (1<<j*4)) % CV_PLUGIN_MAX;
  
                  if( plugins[idx].handle != 0 && name_start )
                  {
                      if( name_end != 0 )
                      {
                          strncpy( name, name_start, name_end - name_start );
                          name[name_end - name_start] = '\0';
                      }
                      else
                          strcpy( name, name_start );
  
                      addr = (uchar*)GetProcAddress( plugins[idx].handle, name );
                      if( addr )
                          break;
                  }
                  name_ptr = name_end;
              }
  
              if( addr )
              {
              /*#ifdef WIN32
                  while( *addr == 0xE9 )
                      addr += 5 + *((int*)(addr + 1));
              #endif*/
                  *func_tab[i].func_addr = addr;
                  func_tab[i].loaded_from = idx; // store index of the module
                                                     // that contain the loaded function
                  loaded_functions++;
                  ICV_PRINTF(("%s: \t%s\n", name, plugins[idx].name ));
              }
  
              #if defined _MSC_VER && _MSC_VER >= 1200
                  #pragma warning( default: 4054 4055 )
              #endif
          }
      }
  
  #if VERBOSE_LOADING
      {
      int not_loaded = 0;
      ICV_PRINTF(("\nTotal loaded: %d\n\n", loaded_functions ));
      printf( "***************************************************\nNot loaded ...\n\n" );
      for( i = 0; func_tab[i].func_addr != 0; i++ )
          if( !func_tab[i].loaded_from )
          {
              ICV_PRINTF(( "%s\n", func_tab[i].func_names ));
              not_loaded++;
          }
  
      ICV_PRINTF(("\nTotal: %d\n", not_loaded ));
      }
  #endif
  
      if( plugins[CV_PLUGIN_OPTCV].handle != 0 )
      {
          for( i = 2; i < CV_PLUGIN_MKL; i++ )
              plugins[i].handle = 0;
      }
  
      return loaded_functions;
  }
  
  
  CV_IMPL int
  cvRegisterModule( const CvModuleInfo* module )
  {
      CvModuleInfo* module_copy = 0;
  
      CV_FUNCNAME( "cvRegisterModule" );
  
      __BEGIN__;
  
      size_t name_len, version_len;
  
      CV_ASSERT( module != 0 && module->name != 0 && module->version != 0 );
  
      name_len = strlen(module->name);
      version_len = strlen(module->version);
  
      CV_CALL( module_copy = (CvModuleInfo*)cvAlloc( sizeof(*module_copy) +
                                          name_len + 1 + version_len + 1 ));
  
      *module_copy = *module;
      module_copy->name = (char*)(module_copy + 1);
      module_copy->version = (char*)(module_copy + 1) + name_len + 1;
  
      memcpy( (void*)module_copy->name, module->name, name_len + 1 );
      memcpy( (void*)module_copy->version, module->version, version_len + 1 );
      module_copy->next = 0;
  
      if( CvModule::first == 0 )
          CvModule::first = module_copy;
      else
          CvModule::last->next = module_copy;
      CvModule::last = module_copy;
  
      if( CvModule::first == CvModule::last )
      {
          CV_CALL( cvUseOptimized(1));
      }
      else
      {
          CV_CALL( icvUpdatePluginFuncTab( module_copy->func_tab ));
      }
  
      __END__;
  
      if( cvGetErrStatus() < 0 && module_copy )
          cvFree( &module_copy );
  
      return module_copy ? 0 : -1;
  }
  
  
  CV_IMPL int
  cvUseOptimized( int load_flag )
  {
      int i, loaded_modules = 0, loaded_functions = 0;
      CvModuleInfo* module;
      const CvProcessorInfo* cpu_info = icvGetProcessorInfo();
      int arch = CV_GET_PROC_ARCH(cpu_info->model);
      
      // TODO: implement some more elegant way
      // to find the latest and the greatest IPP/MKL libraries
      static const char* opencv_sfx[] = { "100", "099", "097", 0 };
      static const char* ipp_sfx_ia32[] = { "-6.1", "-6.0", "-5.2", "-5.1", "", 0 };
      static const char* ipp_sfx_ia64[] = { "64-6.1", "64-6.0", "64-5.2", "64-5.1", "64", 0 };
      static const char* ipp_sfx_em64t[] = { "em64t-6.1", "em64t-6.0", "em64t-5.2", "em64t-5.1", "em64t", 0 };
      static const char* mkl_sfx_ia32[] = { "p4", "p3", "def", 0 };
      static const char* mkl_sfx_ia64[] = { "i2p", "itp", 0 };
      static const char* mkl_sfx_em64t[] = { "def", 0 };
      const char** ipp_suffix = arch == CV_PROC_IA64 ? ipp_sfx_ia64 :
                                arch == CV_PROC_EM64T ? ipp_sfx_em64t : ipp_sfx_ia32;
      const char** mkl_suffix = arch == CV_PROC_IA64 ? mkl_sfx_ia64 :
                                arch == CV_PROC_EM64T ? mkl_sfx_em64t : mkl_sfx_ia32;
  
      for( i = 0; i < CV_PLUGIN_MAX; i++ )
          plugins[i].basename = 0;
      plugins[CV_PLUGIN_NONE].basename = 0;
      plugins[CV_PLUGIN_NONE].name[0] = '\0';
      plugins[CV_PLUGIN_OPTCV].basename = "ippopencv";
      plugins[CV_PLUGIN_IPPCV].basename = "ippcv";
      plugins[CV_PLUGIN_IPPI].basename = "ippi";
      plugins[CV_PLUGIN_IPPS].basename = "ipps";
      plugins[CV_PLUGIN_IPPVM].basename = "ippvm";
      plugins[CV_PLUGIN_IPPCC].basename = "ippcc";
      plugins[CV_PLUGIN_MKL].basename = "mkl_";
  
      // try to load optimized dlls
      for( i = 1; i < CV_PLUGIN_MAX; i++ )
      {
          // unload previously loaded optimized modules
          if( plugins[i].handle )
          {
              FreeLibrary( plugins[i].handle );
              plugins[i].handle = 0;
          }
  
          // do not load regular IPP modules if the custom merged IPP module is already found.
          if( i < CV_PLUGIN_MKL && load_flag && plugins[CV_PLUGIN_OPTCV].handle != 0 )
              continue;
  
          if( load_flag && plugins[i].basename &&
              (arch == CV_PROC_IA32_GENERIC || arch == CV_PROC_IA64 || arch == CV_PROC_EM64T) )
          {
              const char** suffix = i == CV_PLUGIN_OPTCV ? opencv_sfx :
                              i < CV_PLUGIN_MKL ? ipp_suffix : mkl_suffix;
              for( ; *suffix != 0; suffix++ )
              {
                  sprintf( plugins[i].name, DLL_PREFIX "%s%s" DLL_DEBUG_FLAG DLL_SUFFIX,
                      plugins[i].basename, *suffix );
  
                  ICV_PRINTF(("loading %s...\n", plugins[i].name ));
                  plugins[i].handle = LoadLibrary( plugins[i].name );
                  if( plugins[i].handle != 0 )
                  {
                      ICV_PRINTF(("%s loaded\n", plugins[i].name ));
                      loaded_modules++;
                      break;
                  }
                  #ifndef WIN32
                  // temporary workaround for MacOSX 
                  sprintf( plugins[i].name, DLL_PREFIX "%s%s" DLL_DEBUG_FLAG ".dylib",
                      plugins[i].basename, *suffix );
  
                  ICV_PRINTF(("loading %s...\n", plugins[i].name ));
                  plugins[i].handle = LoadLibrary( plugins[i].name );
                  if( plugins[i].handle != 0 )
                  {
                      ICV_PRINTF(("%s loaded\n", plugins[i].name ));
                      loaded_modules++;
                      break;
                  }
                  #endif
              }
          }
      }
  
      for( module = CvModule::first; module != 0; module = module->next )
          loaded_functions += icvUpdatePluginFuncTab( module->func_tab );
  
      return loaded_functions;
  }
  
  CvModule cxcore_module( &cxcore_info );
  
  CV_IMPL void
  cvGetModuleInfo( const char* name, const char **version, const char **plugin_list )
  {
      static char joint_verinfo[1024] = "";
      static char plugin_list_buf[1024] = "";
  
      CV_FUNCNAME( "cvGetLibraryInfo" );
  
      if( version )
          *version = 0;
  
      if( plugin_list )
          *plugin_list = 0;
  
      __BEGIN__;
  
      CvModuleInfo* module;
  
      if( version )
      {
          if( name )
          {
              size_t i, name_len = strlen(name);
  
              for( module = CvModule::first; module != 0; module = module->next )
              {
                  if( strlen(module->name) == name_len )
                  {
                      for( i = 0; i < name_len; i++ )
                      {
                          int c0 = toupper(module->name[i]), c1 = toupper(name[i]);
                          if( c0 != c1 )
                              break;
                      }
                      if( i == name_len )
                          break;
                  }
              }
              if( !module )
                  CV_ERROR( CV_StsObjectNotFound, "The module is not found" );
  
              *version = module->version;
          }
          else
          {
              char* ptr = joint_verinfo;
  
              for( module = CvModule::first; module != 0; module = module->next )
              {
                  sprintf( ptr, "%s: %s%s", module->name, module->version, module->next ? ", " : "" );
                  ptr += strlen(ptr);
              }
  
              *version = joint_verinfo;
          }
      }
  
      if( plugin_list )
      {
          char* ptr = plugin_list_buf;
          int i;
  
          for( i = 0; i < CV_PLUGIN_MAX; i++ )
              if( plugins[i].handle != 0 )
              {
                  sprintf( ptr, "%s, ", plugins[i].name );
                  ptr += strlen(ptr);
              }
  
          if( ptr > plugin_list_buf )
          {
              ptr[-2] = '\0';
              *plugin_list = plugin_list_buf;
          }
          else
              *plugin_list = "";
      }
  
      __END__;
  }
  
  
  typedef int64 (CV_CDECL * rdtsc_func)(void);
  
  /* helper functions for RNG initialization and accurate time measurement */
  CV_IMPL  int64  cvGetTickCount( void )
  {
      const CvProcessorInfo* cpu_info = icvGetProcessorInfo();
  
      if( cpu_info->frequency > 1 &&
          CV_GET_PROC_ARCH(cpu_info->model) == CV_PROC_IA32_GENERIC )
      {
  #ifdef MASM_INLINE_ASSEMBLY
      #ifdef __BORLANDC__
          __asm db 0fh
          __asm db 31h
      #else
          __asm _emit 0x0f;
          __asm _emit 0x31;
      #endif
  #elif (defined __GNUC__ || defined CV_ICC) && defined __i386__
          int64 t;
          asm volatile (".byte 0xf; .byte 0x31" /* "rdtsc" */ : "=A" (t));
          return t;
  #else
          static const char code[] = "\x0f\x31\xc3";
          rdtsc_func func = (rdtsc_func)(void*)code;
          return func();
  #endif
      }
      else
      {
  #if defined WIN32 || defined WIN64
          LARGE_INTEGER counter;
          QueryPerformanceCounter( &counter );
          return (int64)counter.QuadPart;
  #else
          struct timeval tv;
          struct timezone tz;
          gettimeofday( &tv, &tz );
          return (int64)tv.tv_sec*1000000 + tv.tv_usec;
  #endif
      }
  }
  
  CV_IMPL  double  cvGetTickFrequency()
  {
      return icvGetProcessorInfo()->frequency;
  }
  
  
  static int icvNumThreads = 0;
  static int icvNumProcs = 0;
  
  CV_IMPL int cvGetNumThreads(void)
  {
      if( !icvNumProcs )
          cvSetNumThreads(0);
      return icvNumThreads;
  }
  
  CV_IMPL void cvSetNumThreads( int threads )
  {
      if( !icvNumProcs )
      {
  #ifdef _OPENMP
          icvNumProcs = omp_get_num_procs();
          icvNumProcs = MIN( icvNumProcs, CV_MAX_THREADS );
  #else
          icvNumProcs = 1;
  #endif
      }
  
      if( threads <= 0 )
          threads = icvNumProcs;
      else
          threads = MIN( threads, icvNumProcs );
  
      icvNumThreads = threads;
  }
  
  
  CV_IMPL int cvGetThreadNum(void)
  {
  #ifdef _OPENMP
      return omp_get_thread_num();
  #else
      return 0;
  #endif
  }
  
  
  /* End of file. */
  