Search code examples
foreachcmakeexponentiation

How to calculate power index in CMake file


I am working on CMake unit test cases that is using ctest.

I am having one question here.

Some part of my CMake is as below:

set(size_w   32  )
set(powerof2_w  5 )
foreach(size  ${size_w})
  foreach(pwr_of_2  ${powerof2_w})
    ...
    FUNCTION_EXE(${size} ${pwr_of_2})
  endforeach(pwr_of_2)
endforeach(size)

set(size_w   64  )
set(powerof2_w  6 )
foreach(size  ${size_w})
  foreach(pwr_of_2  ${powerof2_w})
    ...
    FUNCTION_EXE(${size} ${pwr_of_2})
  endforeach(pwr_of_2)
endforeach(size)

set(size_w   128  )
set(powerof2_w  7 )
foreach(size  ${size_w})
  foreach(pwr_of_2  ${powerof2_w})
    ...
    FUNCTION_EXE(${size} ${pwr_of_2})
  endforeach(pwr_of_2)
endforeach(size)

set(size_w   256  )
set(powerof2_w  8 )
foreach(size  ${size_w})
  foreach(pwr_of_2  ${powerof2_w})
    ...
    FUNCTION_EXE(${size} ${pwr_of_2})
  endforeach(pwr_of_2)
endforeach(size)

Expectation:

I want to reduce that one loop which is with powerof2_w parameter:

foreach(pwr_of_2  ${powerof2_w})

Is it possible to calculate the pwr_of_2 parameter from the size_w parameter inside the foreach(size ${size_w}) for-loop itself?

Note: Also, I want to combine all four of these for-loops into one for-loop using an array index.

Is this possible in CMake?


Solution

  • If I understand correctly, you are looking to calculate the exponential component for the powers of two for the given sizes:

    32, 64, 128, 256, 512
    

    These are powers of two with corresponding exponents of:

    5, 6, 7, 8, 9
    

    which we can calculate.

    Unfortunately, CMake's math() function does not support exponential arithmetic. But luckily, powers of two are easy to manipulate using bit-shifting, which is supported in CMake. We can create a simple CMake function to calculate the (power of 2) exponents used to derive the sizes 32, 64, 128, etc.

    function(calc_power_of_two_exponent num exponent)
        set(counter 0)
        # Shift until our number equals 1.
        while(num GREATER 1)
            # Right shift by 1
            math(EXPR num "${num} >> 1")
            # Count the number of times we shift.
            math(EXPR counter "${counter} + 1")
        endwhile()
        # Return the number of times shifted, which is the exponent.
        set(exponent ${counter} PARENT_SCOPE)
    endfunction()
    

    It looks like you want to iterate through these size and exponent values in pairs. We can set a list of sizes to iterate over, and calculate the corresponding exponent as we go.

    set(sizes 32 64 128 256 512)
    
    # Iterate through each size.
    foreach(size ${sizes})
        # Call the function to calculate its base-2 power (or index).
        calc_power_of_two_exponent(${size} exponent)
    
        message(STATUS "${size} ${exponent}")
        FUNCTION_EXE(${size} ${exponent})
    endforeach(size)
    

    The status message can be used to confirm we pass the correct values to the FUNCTION_EXE function. This code prints:

    32 5
    64 6
    128 7
    256 8
    512 9