Search code examples
calgorithmconcatenationbit-manipulationmicro-optimization

Decimal concatenation of two integers using bit operations


I want to concatenate two integers using only bit operations since i need efficiency as much as possible.There are various answers available but they are not fast enough what I want is implementation that uses only bit operations like left shift,or and etc. Please guide me how to do it.

example

int x=32;
int y=12;
int result=3212;

I am having and FPGA implentation of AES.I need this on my system to reduce time consumption of some task


Solution

  • The most efficient way to do it, is likely something similar to this:

    uint32_t uintcat (uint32_t ms, uint32_t ls)
    {
      uint32_t mult=1;
    
      do
      {
        mult *= 10; 
      } while(mult <= ls);
    
      return ms * mult + ls;
    }
    

    Then let the compiler worry about optimization. There's likely not a lot it can improve since this is base 10, which doesn't get along well with the various instructions of the computer, like shifting.


    EDIT : BENCHMARK TEST

    Intel i7-3770 2 3,4 GHz
    OS: Windows 7/64
    Mingw, GCC version 4.6.2
    gcc -O3 -std=c99 -pedantic-errors -Wall
    
    10 million random values, from 0 to 3276732767.
    

    Result (approximates):

    Algorithm 1: 60287 micro seconds
    Algorithm 2: 65185 micro seconds
    

    Benchmark code used:

    #include <stdint.h>
    #include <stdio.h>
    #include <windows.h>
    #include <time.h>
    
    uint32_t uintcat (uint32_t ms, uint32_t ls)
    {
      uint32_t mult=1;
    
      do
      {
        mult *= 10; 
      } while(mult <= ls);
    
      return ms * mult + ls;
    }
    
    
    uint32_t myConcat (uint32_t a, uint32_t b) {
        switch( (b >= 10000000) ? 7 : 
                (b >= 1000000) ? 6 : 
                (b >= 100000) ? 5 : 
                (b >= 10000) ? 4 : 
                (b >= 1000) ? 3 : 
                (b >= 100) ? 2 : 
                (b >= 10) ? 1 : 0 ) {
            case 1: return a*100+b; break;
            case 2: return a*1000+b; break;
            case 3: return a*10000+b; break;
            case 4: return a*100000+b; break;
            case 5: return a*1000000+b; break;
            case 6: return a*10000000+b; break;
            case 7: return a*100000000+b; break;
    
            default: return a*10+b; break;
        }
    }
    
    
    static LARGE_INTEGER freq;
    
    static void print_benchmark_results (LARGE_INTEGER* start, LARGE_INTEGER* end)
    {
      LARGE_INTEGER elapsed;
    
      elapsed.QuadPart = end->QuadPart - start->QuadPart;
      elapsed.QuadPart *= 1000000;
      elapsed.QuadPart /= freq.QuadPart;
    
      printf("%lu micro seconds", elapsed.QuadPart);
    }
    
    int main()
    {
      const uint32_t TEST_N = 10000000;
      uint32_t* data1 = malloc (sizeof(uint32_t) * TEST_N);
      uint32_t* data2 = malloc (sizeof(uint32_t) * TEST_N);
      volatile uint32_t* result_algo1 = malloc (sizeof(uint32_t) * TEST_N);
      volatile uint32_t* result_algo2 = malloc (sizeof(uint32_t) * TEST_N);
    
      srand (time(NULL));
      // Mingw rand() apparently gives numbers up to 32767
      // worst case should therefore be 3,276,732,767
    
      // fill up random data in arrays
      for(uint32_t i=0; i<TEST_N; i++)
      {
        data1[i] = rand();
        data2[i] = rand();
      }
    
    
      QueryPerformanceFrequency(&freq); 
    
    
      LARGE_INTEGER start, end;
    
      // run algorithm 1
      QueryPerformanceCounter(&start);
      for(uint32_t i=0; i<TEST_N; i++)
      {
        result_algo1[i] = uintcat(data1[i], data2[i]);
      } 
      QueryPerformanceCounter(&end);
    
      // print results
      printf("Algorithm 1: ");
      print_benchmark_results(&start, &end);
      printf("\n");
    
      // run algorithm 2
      QueryPerformanceCounter(&start);
      for(uint32_t i=0; i<TEST_N; i++)
      {
        result_algo2[i] = myConcat(data1[i], data2[i]);
      } 
      QueryPerformanceCounter(&end);
    
      // print results
      printf("Algorithm 2: ");
      print_benchmark_results(&start, &end);
      printf("\n\n");
    
    
      // sanity check both algorithms against each other
      for(uint32_t i=0; i<TEST_N; i++)
      {
        if(result_algo1[i] != result_algo2[i])
        {
          printf("Results mismatch for %lu %lu. Expected: %lu%lu, algo1: %lu, algo2: %lu\n",
                 data1[i], 
                 data2[i],
                 data1[i],
                 data2[i],
                 result_algo1[i],
                 result_algo2[i]);
        }
      }
    
    
      // clean up
      free((void*)data1);
      free((void*)data2);
      free((void*)result_algo1);
      free((void*)result_algo2);
    }