////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-2020 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxutils.h
/// @brief Various static inline utility functions
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXUTILS_H
#define CAMXUTILS_H

#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h>

#ifdef _WINDOWS
// NOWHINE FILE PR006:
#pragma warning (disable : 4100) // unreferenced formal parameter
#endif // _WINDOWS

#include "camxdefs.h"
#include "camxdebug.h"
#include "camxmem.h"
#include "camxtypes.h"
#include "camxcdktypes.h"

#ifdef BitScanForward       // NOWHINE PR002 <- Win32 definition
#undef BitScanForward
#endif // BitScanForward
#ifdef BitScanReverse       // NOWHINE PR002 <- Win32 definition
#undef BitScanReverse
#endif // BitScanReverse


CAMX_NAMESPACE_BEGIN

const UINT64 MicroMetersPerMilliMeter   = 1000ULL;

typedef union {
    int32_t i32;
    float   f32;
} floatint_32;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Utils
///
/// @brief General utility class implementation
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Utils
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Result Code Functions
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CamxResultToErrno
    ///
    /// @brief  Converts a CamxResult result code to an errno result code
    ///
    /// @param  result The CamxResult result code to convert
    ///
    /// @return The errno code corresponding to the CamxResult result code
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // NOWHINE GR017: Converting to int type for top-level API
    static CAMX_INLINE int CamxResultToErrno(
        CamxResult result)
    {
        // NOWHINE GR017: Converting to int type for top-level API
        int errnoResult = 0;

        switch (result)
        {
            case CamxResultSuccess:
                errnoResult = 0;
                break;
            case CamxResultEFailed:
                errnoResult = -ENODEV;
                break;
            case CamxResultEUnsupported:
                errnoResult = -EPERM;
                break;
            case CamxResultEInvalidState:
                errnoResult = -EPERM;
                break;
            case CamxResultEInvalidArg:
                errnoResult = -EINVAL;
                break;
            case CamxResultEInvalidPointer:
                errnoResult = -EFAULT;
                break;
            case CamxResultENoSuch:
                errnoResult = -EINVAL;
                break;
            case CamxResultEOutOfBounds:
                errnoResult = -EINVAL;
                break;
            case CamxResultENoMemory:
                errnoResult = -ENOMEM;
                break;
            case CamxResultETimeout:
                errnoResult = -ETIME;
                break;
            case CamxResultENoMore:
                errnoResult = -ENODATA;
                break;
            case CamxResultENeedMore:
                errnoResult = -EPERM;
                break;
            case CamxResultEExists:
                errnoResult = -EEXIST;
                break;
            case CamxResultEPrivLevel:
                errnoResult = -EACCES;
                break;
            case CamxResultEResource:
                errnoResult = -EPERM;
                break;
            case CamxResultEUnableToLoad:
                errnoResult = -1;
                break;
            case CamxResultEInProgress:
                errnoResult = -EINPROGRESS;
                break;
            case CamxResultETryAgain:
                errnoResult = -EAGAIN;
                break;
            case CamxResultEBusy:
                errnoResult = -EBUSY;
                break;
            case CamxResultEReentered:
                errnoResult = -EPERM;
                break;
            case CamxResultEReadOnly:
                errnoResult = -EPERM;
                break;
            case CamxResultEOverflow:
                errnoResult = -EOVERFLOW;
                break;
            case CamxResultEOutOfDomain:
                errnoResult = -EDOM;
                break;
            case CamxResultEInterrupted:
                errnoResult = -EINTR;
                break;
            case CamxResultEWouldBlock:
                errnoResult = -EPERM;
                break;
            case CamxResultETooManyUsers:
#if defined (_WIN32)
                errnoResult = -68;
#else // WIN32
                errnoResult = -EUSERS;
#endif // WIN32
                break;
            case CamxResultENotImplemented:
                errnoResult = -ENOSYS;
                break;
            default:
                break;
        }

        return errnoResult;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CamxResultToString
    ///
    /// @brief  Converts a CamxResult result code to a string represents the error
    ///
    /// @param  result The CamxResult result code to convert
    ///
    /// @return The error string represents the error
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE const CHAR* CamxResultToString(
        CamxResult result)
    {
        CamxResult resultDefault = CamxResultEFailed;
        if ((result >= 0) &&
            (result < CamxResultCount))
        {
            resultDefault = result;
        }

        return CamxResultStrings[resultDefault];
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BoolToString
    ///
    /// @brief  Converts a BOOL to a string value for printing
    ///
    /// @param  val The boolean value to print
    ///
    /// @return "true", "false", or "Out of range" for BOOLS that are neither TRUE or FALSE.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE const CHAR* BoolToString(
        BOOL val)
    {
        switch (val)
        {
            case FALSE:
                return "false";
            case TRUE:
                return "true";
            default:
                return "Out of range";
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Math Functions
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetInterpolationRatio
    ///
    /// @brief  Calculate ratio of a FLOAT value within certain range
    ///
    /// @param  input      Input value to be interpolated. Its value should be between startValue and endValue.
    /// @param  startValue Start value
    /// @param  endValue   End value
    ///
    /// @return Interpolation Ratio (0.0f to 1.0f)
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE FLOAT GetInterpolationRatio(
        FLOAT input,
        FLOAT startValue,
        FLOAT endValue)
    {
        FLOAT output = 0.0f;

        if ((endValue != startValue) &&
            (input    >= startValue) &&
            (input    <= endValue))
        {
            output = 1.0f - (input - startValue)/(endValue - startValue);
        }
        else
        {
            output = 0.0f;
            CAMX_ASSERT_ALWAYS();
        }

        return output;
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsUINT32Odd
    ///
    /// @brief  Check if UINT32 is odd number
    ///
    /// @param  input input value to be checked for odd
    ///
    /// @return UINT32 True if input is odd number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 IsUINT32Odd(
        UINT32 input)
    {
        return ((input & 0x0001) ? TRUE : FALSE);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsINT32Odd
    ///
    /// @brief  Check if INT32 is odd number
    ///
    /// @param  input input value to be checked for odd
    ///
    /// @return UINT32 True if input is odd number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 IsINT32Odd(
        INT32 input)
    {
        return ((input & 0x0001) ? TRUE : FALSE);
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsUINT32Even
    ///
    /// @brief  Check if UINT32 is Even number
    ///
    /// @param  input input value to be checked for Even
    ///
    /// @return UINT32 True if input is Even number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 IsUINT32Even(
        UINT32 input)
    {
        return ((input & 0x0001) ? FALSE : TRUE);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsINT32Even
    ///
    /// @brief  Check if INT32 is Even number
    ///
    /// @param  input input value to be checked for Even
    ///
    /// @return UINT32 True if input is Even number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT32 IsINT32Even(
        INT32 input)
    {
        return ((input & 0x0001) ? FALSE : TRUE);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OddFloorUINT32
    ///
    /// @brief  Floor UINT32 to Odd number
    ///
    /// @param  input input value to be rounded down
    ///
    /// @return UINT32 Rounded down value of input
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 OddFloorUINT32(
        UINT32 input)
    {
        UINT32 result;

        if (0 == input)
        {
            result = 0;
        }
        else if (0 != (input & 0x00000001))
        {
            result = input;
        }
        else
        {
            result = input - 0x00000001;
        }
        return result;
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OddFloorINT32
    ///
    /// @brief  Floor INT32 to Odd number
    ///
    /// @param  input input value to be rounded down
    ///
    /// @return INT32 Rounded down value of input
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT32 OddFloorINT32(
        INT32 input)
    {
        INT32 result;

        if (0 == input)
        {
            result = 0;
        }
        else if (0 != (input & 0x00000001))
        {
            result = input;
        }
        else
        {
            result = input - 0x00000001;
        }
        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// EvenFloorUINT32
    ///
    /// @brief  Floor UINT32 to Even number
    ///
    /// @param  input input value to be rounded down
    ///
    /// @return UINT32 Rounded down value of input
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 EvenFloorUINT32(
        UINT32 input)
    {
        return (input & 0xFFFFFFFE);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// EvenFloorINT32
    ///
    /// @brief  Floor INT32 to Even number
    ///
    /// @param  input input value to be rounded down
    ///
    /// @return UINT32 Rounded down value of input
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT32 EvenFloorINT32(
        INT32 input)
    {
        return (input & 0xFFFFFFFE);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OddCeilingUINT32
    ///
    /// @brief  Ceil UINT32 to Odd number
    ///
    /// @param  input input value to be rounded up
    ///
    /// @return UINT32 Rounded up value of input
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 OddCeilingUINT32(
        UINT32 input)
    {
        return (input | 0x00000001);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OddCeilingINT32
    ///
    /// @brief  Ceil INT32 to Odd number
    ///
    /// @param  input input value to be rounded up
    ///
    /// @return INT32 Rounded up value of input
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT32 OddCeilingINT32(
        INT32 input)
    {
        return (input | 0x00000001);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// EvenCeilingUINT32
    ///
    /// @brief  Ceil UINT32 to Even number
    ///
    /// @param  input input value to be rounded up
    ///
    /// @return UINT32 Rounded up value of input
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 EvenCeilingUINT32(
        UINT32 input)
    {
        UINT32 result;

        if (0xFFFFFFFF == input)
        {
            result = input;
        }
        else if (0 != (input & 0x00000001))
        {
            result = input + 0x00000001;
        }
        else
        {
            result = input;
        }
        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// EvenCeilingINT32
    ///
    /// @brief  Ceil INT32 to Even number
    ///
    /// @param  input input value to be rounded up
    ///
    /// @return UINT32 Rounded up value of input
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT32 EvenCeilingINT32(
        INT32 input)
    {
        INT32 result;

        if (0x7FFFFFFF == input)
        {
            result = input;
        }
        else if (0 != (input & 0x00000001))
        {
            result = input + 0x00000001;
        }
        else
        {
            result = input;
        }
        return result;
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DivideAndCeil
    ///
    /// @brief  calculates the ceil after dividing a UINT32
    ///
    /// @param  val     UINT32 to be divided and ceiled
    /// @param  divisor UINT32 to use as the divisor in the operation
    ///
    /// @return UINT32  ceil of the quotient
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 DivideAndCeil(
        UINT32 val,
        UINT32 divisor)
    {
        CAMX_ASSERT(divisor != 0);
        return (val + (divisor - 1)) / divisor;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FloorUINT32
    ///
    /// @brief  Floor UINT32 to multiple of base floor value
    ///
    /// @param  floor the base number to which value should be floored
    /// @param  input input value to be floored
    ///
    /// @return UINT32 Floored input value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 FloorUINT32(
        UINT32 floor,
        UINT32 input)
    {
        return (input & (0xFFFFFFFF - (floor - 1)));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ClampUINT32
    ///
    /// @brief  Clamp UINT32 to the range of maximum and minimum
    ///
    /// @param  input1 input value to be clamped
    /// @param  min    Minimum value, below which the input will be clamped
    /// @param  max    Maximum value, beyond which the input will be clamped
    ///
    /// @return UINT32 Input if it is range of max and minimum, else clamped value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 ClampUINT32(
        UINT32 input1,
        UINT32 min,
        UINT32 max)
    {
        return (((input1) <= (min)) ? (min) : (((input1) >= (max)) ? (max) : (input1)));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ClampINT32
    ///
    /// @brief  Clamp INT32 to the range of maximum and minimum
    ///
    /// @param  input1 input value to be clamped
    /// @param  min    Minimum value, bellow which the input will be clamped
    /// @param  max    Maximum value, beyond which the input will be clamped
    ///
    /// @return UINT32 Input if it is range of max and minimum, else clamped value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT32 ClampINT32(
        INT32 input1,
        INT32 min,
        INT32 max)
    {
        return (((input1) <= (min)) ? (min) : (((input1) >= (max)) ? (max) : (input1)));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ClampFLOAT
    ///
    /// @brief  Clamp FLOAT to the range of maximum and minimum
    ///
    /// @param  input1 input value to be clamped
    /// @param  min    Minimum value, bellow which the input will be clamped
    /// @param  max    Maximum value, beyond which the input will be clamped
    ///
    /// @return UINT32 Input if it is range of max and minimum, else clamped value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE FLOAT ClampFLOAT(
        FLOAT input1,
        FLOAT min,
        FLOAT max)
    {
        return (((input1) <= (min)) ? (min) : (((input1) >= (max)) ? (max) : (input1)));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RoundFLOAT
    ///
    /// @brief  Round the FLOAT to Nearest INT
    ///
    /// @param  input input value
    ///
    /// @return Round to the nearest int value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT RoundFLOAT(
        FLOAT input)
    {
        return static_cast<INT>(roundf(input));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RoundFLOATtoNDecimalPlaces
    ///
    /// @brief  Round the FLOAT to N Precision
    ///
    /// @param  input input value
    /// @param  n     number of precision
    ///
    /// @return Round to the nearest N decimal Places
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE FLOAT RoundFLOATtoNDecimalPlaces(
        FLOAT input, UINT32 n)
    {
        UINT32 powerOfN = (static_cast<UINT64>(pow(10, n)) > UINT32_MAX) ?
            static_cast<UINT32>(pow(10, log10(UINT32_MAX))) : static_cast<UINT32>(pow(10, n));
        INT64 value     = input > 0 ? static_cast<INT64>(input * powerOfN + 0.5f) :
                                static_cast<INT64>(input * powerOfN - 0.5f);
        FLOAT result    = static_cast<FLOAT>(value)/ static_cast<FLOAT>(powerOfN);

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CellingFLOAT
    ///
    /// @brief  Increase float by minimum machine epsilon
    ///
    /// @param  value The float number to operate
    ///
    /// @return The float + float machine epsilon
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE FLOAT CellingFLOAT(
        FLOAT value)
    {
        floatint_32 s;

        s.f32 = value;
        s.i32++;

        return s.f32;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Power
    ///
    /// @brief  Utility to return the base raised to the power of exponent
    ///
    /// @param  base     Value to be used a base
    /// @param  exponent Value to be which the base should be raised to
    ///
    /// @return base to the power of exponent
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE DOUBLE Power(
        DOUBLE base,
        DOUBLE exponent)
    {
        DOUBLE result = 0.0;

        if (0.0 == exponent)
        {
            result = 1.0;
        }
        else if (0.0 != base)
        {
            result = pow(base, exponent);
        }
        else
        {
            result = 0.0;
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AbsoluteINT32
    ///
    /// @brief  Find the absolute value of a INT32
    ///
    /// @param  input input value
    ///
    /// @return Absolute value of the input INT32 value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 AbsoluteINT32(
        INT32 input)
    {
        return static_cast<UINT32>(abs(input));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AbsoluteINT64
    ///
    /// @brief  Find the absolute value of a INT64
    ///
    /// @param  input input value
    ///
    /// @return Absolute value of the input INT64 value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT64 AbsoluteINT64(
        INT64 input)
    {
        return static_cast<UINT64>(llabs(input));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// RoundDOUBLE
    ///
    /// @brief  Round the DOUBLE to Nearest INT64
    ///
    /// @param  input input value
    ///
    /// @return Round to the nearest int64 value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT64 RoundDOUBLE(
        DOUBLE input)
    {
        return static_cast<INT64>(llroundl(input));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AbsoluteFLOAT
    ///
    /// @brief  Find the absolute value of a FLOAT
    ///
    /// @param  input input value
    ///
    /// @return Absolute value of the input FLOAT value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE DOUBLE AbsoluteFLOAT(
        FLOAT input)
    {
        return fabs(input);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SqrtF
    ///
    /// @brief  Find the square root value of a FLOAT
    ///
    /// @param  input input value
    ///
    /// @return Square root value of the input FLOAT value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE FLOAT SqrtF(
        FLOAT input)
    {
        return static_cast<FLOAT>(sqrt(input));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Sqrt
    ///
    /// @brief  Find the square root value of a DOUBLE
    ///
    /// @param  input input value
    ///
    /// @return Square root value of the input DOUBLE value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE DOUBLE Sqrt(
        DOUBLE input)
    {
        return sqrt(input);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// LinearInterpolationINT
    ///
    /// @brief  Perform Linear Interpolation for INT value.
    ///
    /// @param  input1 Interpolation range end value
    /// @param  input2 Interpolation range start value
    /// @param  ratio  ratio value
    ///
    /// @return Pointer to the Matrix
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT LinearInterpolationINT(
        INT   input1,
        INT   input2,
        FLOAT ratio)
    {
        return RoundFLOAT(input2 + (ratio * (input1 - input2)));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// LinearInterpolationFLOAT
    ///
    /// @brief  Perform Linear Interpolation, Input is Float
    ///
    /// @param  input1 Interpolation range end value
    /// @param  input2 Interpolation range start value
    /// @param  ratio  ratio value
    ///
    /// @return Pointer to the Matrix
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE FLOAT LinearInterpolationFLOAT(
        FLOAT input1,
        FLOAT input2,
        FLOAT ratio)
    {
        return (input2 + (ratio * (input1 - input2)));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetUnityMatrix
    ///
    /// @brief  Set the Input Matrix to the Unity Matrix
    ///
    /// @param  pIn        pointer to the input Matrix
    /// @param  matrixSize inputMatrix is of size x size
    ///
    /// @return Pointer to the unity  matrix
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE FLOAT* SetUnityMatrix(
        FLOAT* pIn,
        UINT   matrixSize)
    {
        UINT countI = 0;
        UINT countJ = 0;

        if ((NULL != pIn) && (matrixSize > 0))
        {
            for (countI = 0; countI < matrixSize; countI++)
            {
                for (countJ = 0; countJ < matrixSize; countJ++)
                {
                    if (countI == countJ)
                    {
                        pIn[countJ + countI * matrixSize] = 1.0f;
                    }
                    else
                    {
                        pIn[countJ + countI * matrixSize] = 0.0f;
                    }
                }
            }
        }

        return pIn;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MatrixMultiply
    ///
    /// @brief  Multiply two matrices
    ///
    /// @param  pIn1        Pointer to the input Matrix1
    /// @param  pIn2        Pointer to the input Matrix2
    /// @param  pOut        Pointer to the output Matrix
    /// @param  matrixSize  Matrix is of size x size
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID MatrixMultiply(
        FLOAT (*pIn1)[3],
        FLOAT (*pIn2)[3],
        FLOAT (*pOut)[3],
        UINT  matrixSize)
    {
        UINT countI = 0;
        UINT countJ = 0;
        UINT countK = 0;
        if ((NULL != pIn1) && (NULL != pIn2) && (NULL != pOut) && (matrixSize > 0))
        {
            for (countI = 0; countI < matrixSize; countI++)
            {
                for (countJ = 0; countJ < matrixSize; countJ++)
                {
                    pOut[countI][countJ] = 0;
                    for (countK = 0; countK < matrixSize; countK++)
                    {
                        pOut[countI][countJ] += (pIn1[countI][countK] * pIn2[countK][countJ]);
                    }
                }
            }
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MatrixInverse3x3
    ///
    /// @brief  Compute Inverse of a matrix
    ///
    /// @param  pIn        Pointer to the input Matrix
    /// @param  pOut       Pointer to the output Matrix
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL MatrixInverse3x3(
        FLOAT* pIn,
        FLOAT* pOut)
    {
        BOOL result = TRUE;
        FLOAT det   = 0.0f;

        if ((NULL != pIn) && (NULL != pOut))
        {
            det = pIn[0] * (pIn[4] * pIn[8] - pIn[5] * pIn[7]) +
                  pIn[1] * (pIn[5] * pIn[6] - pIn[3] * pIn[8]) +
                  pIn[2] * (pIn[3] * pIn[7] - pIn[4] * pIn[6]);
            if (FEqual(det, 0.0f))
            {
                result = FALSE;
            }
            else
            {
                pOut[0] = (pIn[4] * pIn[8] - pIn[5] * pIn[7]) / det;
                pOut[1] = (pIn[2] * pIn[7] - pIn[1] * pIn[8]) / det;
                pOut[2] = (pIn[1] * pIn[5] - pIn[2] * pIn[4]) / det;
                pOut[3] = (pIn[5] * pIn[6] - pIn[3] * pIn[8]) / det;
                pOut[4] = (pIn[0] * pIn[8] - pIn[2] * pIn[6]) / det;
                pOut[5] = (pIn[2] * pIn[3] - pIn[0] * pIn[5]) / det;
                pOut[6] = (pIn[3] * pIn[7] - pIn[4] * pIn[6]) / det;
                pOut[7] = (pIn[1] * pIn[6] - pIn[0] * pIn[7]) / det;
                pOut[8] = (pIn[0] * pIn[4] - pIn[1] * pIn[3]) / det;
            }
        }
        else
        {
            result = FALSE;
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsPowerOfTwo
    ///
    /// @brief  Checks if a value is a power of 2
    ///
    /// @param  val    value to check
    ///
    /// @return TRUE if the number is a power of 2, FALSE otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsPowerOfTwo(
        SIZE_T val)
    {
        return ((val == 0) ? FALSE : (((val & (val - 1)) == 0) ? TRUE : FALSE));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ByteAlignFloor
    ///
    /// @brief  This function is used to align down any SIZE_T value to a specific power of 2
    ///
    /// @param  operand     value to be aligned
    /// @param  alignment   desired alignment
    ///
    /// @return Value aligned as specified
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE SIZE_T ByteAlignFloor(
        SIZE_T operand,
        UINT   alignment)
    {
        // This function only works for a power-of-2 alignment.
        CAMX_ASSERT(IsPowerOfTwo(alignment));

        return ((operand) & ~(static_cast<SIZE_T>(alignment) - 1));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ByteAlignFloor64
    ///
    /// @brief  This function is used to align down any UINT64 value to a specific power of 2
    ///
    /// @param  operand      value to be aligned
    /// @param  alignment    desired alignment
    ///
    /// @return Value aligned as specified
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT64 ByteAlignFloor64(
        UINT64 operand,
        UINT   alignment)
    {
        // This function only works for a power-of-2 alignment
        CAMX_ASSERT(IsPowerOfTwo(alignment));

        return ((operand) & ~(static_cast<UINT64>(alignment) - 1));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ByteAlignFloorPtr
    ///
    /// @brief  This function is used to align down a pointer to a specific power of 2 BYTE boundary
    ///
    /// @param  pMem        pointer to be aligned
    /// @param  alignBytes  desired alignment in bytes
    ///
    /// @return Pointer aligned down as specified
    ///
    /// @remark Use The ByteAlignFloor() function for non-pointer alignment
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID* ByteAlignFloorPtr(
        VOID*  pMem,
        UINT   alignBytes)
    {
        // This function only works for a power-of-2 alignment
        CAMX_ASSERT(IsPowerOfTwo(alignBytes));

        return reinterpret_cast<VOID*>((reinterpret_cast<SIZE_T>(pMem)) & ~(static_cast<SIZE_T>(alignBytes) - 1));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ByteAlign
    ///
    /// @brief  This function is used to align up any SIZE_T value to a specific power of 2
    ///
    /// @param  operand     value to be aligned
    /// @param  alignment   desired alignment
    ///
    /// @return Value aligned as specified
    ///
    /// @remark Use The ByteAlignPtr() function for pointer calculations
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE SIZE_T ByteAlign(
        SIZE_T operand,
        UINT   alignment)
    {
        // This function only works for a power-of-2 alignment.
        CAMX_ASSERT(IsPowerOfTwo(alignment));

        return ((operand + (alignment - 1)) & ~(static_cast<SIZE_T>(alignment) - 1));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ByteAlign64
    ///
    /// @brief  This function is used to align up any UINT64 value to a specific power of 2
    ///
    /// @param  operand     value to be aligned
    /// @param  alignment   desired alignment
    ///
    /// @return Value aligned as specified
    ///
    /// @remark Use The ByteAlignPtr() function for pointer calculations
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT64 ByteAlign64(
        UINT64 operand,
        UINT   alignment)
    {
        // This function only works for a power-of-2 alignment
        CAMX_ASSERT(IsPowerOfTwo(alignment));

        return ((operand + (alignment - 1)) & ~(static_cast<UINT64>(alignment) - 1));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ByteAlign32
    ///
    /// @brief  This function is used to align up any UINT32 value to a specific power of 2
    ///
    /// @param  operand     value to be aligned
    /// @param  alignment   desired alignment
    ///
    /// @return Value aligned as specified
    ///
    /// @remark Use The ByteAlignPtr() function for pointer calculations
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 ByteAlign32(
        UINT32 operand,
        UINT   alignment)
    {
        // This function only works for a power-of-2 alignment
        CAMX_ASSERT(IsPowerOfTwo(alignment));

        return ((operand + (alignment - 1)) & ~(static_cast<UINT32>(alignment) - 1));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ByteAlignPtr
    ///
    /// @brief  This function is used to align a pointer to a specific power of 2 BYTE boundary
    ///
    /// @param  pMem        pointer to be aligned
    /// @param  alignBytes  desired alignment in bytes
    ///
    /// @return Pointer aligned as specified
    ///
    /// @remark Use The ByteAlign() function for non-pointer alignment
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID* ByteAlignPtr(
        VOID*  pMem,
        SIZE_T alignBytes)
    {
        // This function only works for a power-of-2 alignment
        CAMX_ASSERT(IsPowerOfTwo(alignBytes));

        return reinterpret_cast<VOID*>((reinterpret_cast<SIZE_T>(pMem) + (alignBytes - 1)) &
                                       ~(static_cast<SIZE_T>(alignBytes) - 1));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AlignGeneric32
    ///
    /// @brief  This function is used to align up any UINT32 value to any alignment value
    ///
    /// @param  operand     value to be aligned
    /// @param  alignment   desired alignment
    ///
    /// @return Value aligned as specified
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 AlignGeneric32(
        UINT32 operand,
        UINT   alignment)
    {
        UINT remainder = (operand % alignment);

        return (0 == remainder) ? operand : operand - remainder + alignment;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AlignNearGeneric32
    ///
    /// @brief  This function is used to align to near any UINT32 value to any alignment value
    ///
    /// @param  operand                  value to be aligned
    /// @param  midNextAlignemnt         at mid point align to next aligned value
    /// @param  alignment                desired alignment
    ///
    /// @return Value aligned as specified
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 AlignNearGeneric32(
        UINT32 operand,
        BOOL   midNextAlignemnt,
        UINT   alignment)
    {
        UINT remainder     = (operand % alignment);
        UINT32 returnvalue = operand - remainder;
        if ((remainder > (alignment / 2)) || ((remainder == (alignment / 2)) &&
            midNextAlignemnt))
        {
            returnvalue = operand - remainder + alignment;
        }
        return returnvalue;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Ceiling
    ///
    /// @brief  This function finds the integer ceiling of a FLOAT precision operand
    ///
    /// @param  operand value whose ceiling needs to be calculated
    ///
    /// @return Integer ceiling
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 Ceiling(
        FLOAT operand)
    {
        return static_cast<UINT32>(ceil(operand));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Floor
    ///
    /// @brief  This function finds the integer floor of a FLOAT precision operand
    ///
    /// @param  operand value whose floor needs to be calculated
    ///
    /// @return Integer floor
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 Floor(
        FLOAT operand)
    {
        return static_cast<UINT32>(floor(operand));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MinBitsUINT32
    ///
    /// @brief  This function finds the minimum number of bits required to represent the operand value.
    ///
    /// @param  operand     UINT32 number
    ///
    /// @return Minimum number of bits required to represent the operand value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 MinBitsUINT32(
        UINT32 operand)
    {
        UINT32 value = 0;

        if (0 == operand)
        {
            return 1; // Zero needs at least one bit to be represented
        }

        while (1 <= operand)
        {
            value++;
            operand >>= 1;
        }

        return value;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitScanForward
    ///
    /// @brief  Search the mask data from least significant bit (LSB) to most significant bit (MSB) for a set bit (1)
    ///
    /// @param  number  The 32-bit value to search.
    /// @param  pIndex  Loaded with the bit position of the first set bit (1) found, set to 0 if no bits are set in number
    ///
    /// @return TRUE if found, FALSE otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL BitScanForward(
        UINT32  number,
        UINT32* pIndex)
    {
        UINT32  mask = number;
        BOOL    result;

        if (mask != 0)
        {
            // get first 1 bit's position (from LSB) in mask
#if defined (_WIN32)
            // NOWHINE GR017: The native type uses unsigned long
            _BitScanForward(reinterpret_cast<unsigned long*>(pIndex), mask);
#elif defined(__GNUC__)
            *pIndex = __builtin_ctz(mask);      // Count Trailing Zeros
#else
            CAMX_STATIC_ASSERT2(FALSE, "Unsupported Target");
#endif // defined (_WIN32)/defined(__GNUC__)
            result = TRUE;
        }
        else
        {
            result = FALSE;
            /// @note The contents of pIndex when there are no set bits in mask are undefined according to the underlying
            ///      behavior of the instructions used to implement the intrinsic.  Explicitly reset the value to 0 and avoid
            ///      relying on compiler/platform dependent behavior.
            *pIndex = 0;
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitScanForwardArray
    ///
    /// @brief  Search the mask data from least significant bit (LSB) to most significant bit (MSB) for a set bit (1)
    ///
    /// @param  pNumber     Ptr to the array to bitscan
    /// @param  arraySize   Number of array indexes (1 based)
    /// @param  pIndex      Loaded with the bit position of the first set bit (1) found, set to 0 if no bits are set in number
    ///
    /// @return TRUE if found, FALSE otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL BitScanForwardArray(
        const UINT* pNumber,
        UINT        arraySize,
        UINT32*     pIndex)
    {
        BOOL result = FALSE;

        CAMX_ASSERT(arraySize != 0);

        for (UINT i = 0; i < arraySize; i++)
        {
            CAMX_ASSERT((pNumber != NULL) && (pIndex != NULL));

            if (TRUE == BitScanForward(pNumber[i], pIndex))
            {
                result = TRUE;
                // BitScan is zero based however we do need to multiply by the array index
                // to get bit > 31
                (*pIndex) += (i * 32);
                break;
            }
        }
        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitScanReverse
    ///
    /// @brief  Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1)
    ///
    /// @param  number      The 32-bit value to search
    /// @param  pIndex      Loaded with the bit position of the first set bit (1) found, set to 0 if no bits are set in number
    ///
    /// @return TRUE if found, FALSE otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL BitScanReverse(
        UINT32  number,
        UINT32* pIndex)
    {
        UINT32  mask = number;
        BOOL    result;

        if (mask != 0)
        {
            // get first 1 bit's position (from MSB) in mask
#if defined (_WIN32)
            // NOWHINE GR017: The native type uses unsigned long
            _BitScanReverse(reinterpret_cast<unsigned long*>(pIndex), mask);
#elif defined(__GNUC__)
            *pIndex = 31 - __builtin_clz(mask);      // Count Leading Zeros
#else
            CAMX_STATIC_ASSERT2(FALSE, "Unsupported Target");
#endif // defined (_WIN32)/defined(__GNUC__)
            result = TRUE;
        }
        else
        {
            result = FALSE;
            /// @note The contents of pIndex when there are no set bits in mask are undefined according to the underlying
            ///      behavior of the instructions used to implement the intrinsic.  Explicitly reset the value to 0 and avoid
            ///      relying on compiler/platform dependent behavior.
            *pIndex = 0;
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitScanReverseArray
    ///
    /// @brief  Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1)
    ///
    /// @param  pNumber     Ptr to the array to bitscan
    /// @param  arraySize   Number of array indexes (1 based)
    /// @param  pIndex      Loaded with the bit position of the first set bit (1) found, set to 0 if no bits are set in number
    ///
    /// @return TRUE if found, FALSE otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL BitScanReverseArray(
        const UINT* pNumber,
        UINT        arraySize,
        UINT32*     pIndex)
    {
        BOOL result = FALSE;

        CAMX_ASSERT(arraySize != 0);

        for (INT i = (arraySize - 1); i >= 0; i--)
        {
            CAMX_ASSERT((pNumber != NULL) && (pIndex != NULL));

            if (TRUE == BitScanReverse(pNumber[i], pIndex))
            {
                result = TRUE;
                // BitScan is zero based however we do need to multiply by the array index
                // to get bit > 31
                (*pIndex) += (i * 32);
                break;
            }
        }
        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitReset
    ///
    /// @brief  Reset a particular bit to 0
    ///
    /// @param  number  Number whose bit needs to be set
    /// @param  bit     Bit number to set
    ///
    /// @return Resulting number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 BitReset(
        UINT32  number,
        UINT32  bit)
    {
        static const UINT32 One = 1;     /// @note Forces type of literal constant without relying on suffix

        CAMX_ASSERT(bit < (sizeof(UINT32) * 8));

        return (number & ~(One << bit));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitReset64
    ///
    /// @brief  Reset a particular bit to 0
    ///
    /// @param  number  Number whose bit needs to be set
    /// @param  bit     Bit number to set
    ///
    /// @return Resulting number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT64 BitReset64(
        UINT64  number,
        UINT64  bit)
    {
        static const UINT64 One = 1;     /// @note Forces type of literal constant without relying on suffix

        CAMX_ASSERT(bit < (sizeof(UINT64) * 8));

        return (number & ~(One << bit));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitSet
    ///
    /// @brief  Sets a particular bit to 1
    ///
    /// @param  number  Number whose bit needs to be set
    /// @param  bit     Bit number to set
    ///
    /// @return Resulting number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 BitSet(
        UINT32  number,
        UINT32  bit)
    {
        static const UINT32 One = 1;     /// @note Forces type of literal constant without relying on suffix

        CAMX_ASSERT(bit < (sizeof(UINT32) * 8));

        return (number | (One << bit));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitSet64
    ///
    /// @brief  Sets a particular bit to 1
    ///
    /// @param  number  Number whose bit needs to be set
    /// @param  bit     Bit number to set
    ///
    /// @return Resulting number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT64 BitSet64(
        UINT64  number,
        UINT64  bit)
    {
        static const UINT64 One = 1;     /// @note Forces type of literal constant without relying on suffix

        CAMX_ASSERT(bit < (sizeof(UINT64) * 8));

        return (number | (One << bit));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitMaskReset
    ///
    /// @brief  Resets all bits in number that are set in mask
    ///
    /// @param  number  Number whose bits need to be reset
    /// @param  mask    Bit mask
    ///
    /// @return Resulting number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 BitMaskReset(
        UINT32  number,
        UINT32  mask)
    {
        return (number & ~mask);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// BitMaskSet
    ///
    /// @brief  Sets all bits in number that are set in mask
    ///
    /// @param  number  Number whose bits need to be set
    /// @param  mask    Bit mask
    ///
    /// @return Resulting number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 BitMaskSet(
        UINT32  number,
        UINT32  mask)
    {
        return (number | mask);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsBitMaskReset
    ///
    /// @brief  Tests if all bits set in mask are reset in number
    ///
    /// @param  number  Number to test
    /// @param  mask    Bit mask
    ///
    /// @return TRUE if test passes
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsBitMaskReset(
        UINT32  number,
        UINT32  mask)
    {
        return ((number & mask) == 0) ? TRUE : FALSE;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsBitMaskSet
    ///
    /// @brief  Tests if all bits set in mask are set in number
    ///
    /// @param  number  Number to test
    /// @param  mask    Bit mask
    ///
    /// @return TRUE if test passes
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsBitMaskSet(
        UINT32  number,
        UINT32  mask)
    {
        return ((number & mask) == mask) ? TRUE : FALSE;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsBitReset
    ///
    /// @brief  Tests if a bit is reset in number
    ///
    /// @param  number  Number to test
    /// @param  bit     Bit number to test
    ///
    /// @return TRUE if test passes.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsBitReset(
        UINT32  number,
        UINT32  bit)
    {
        static const UINT32 One = 1;     /// @note Forces type of literal constant without relying on suffix

        CAMX_ASSERT(bit < (sizeof(UINT32) * 8));

        return ((number & (One << bit)) == 0) ? TRUE : FALSE;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsBitReset64
    ///
    /// @brief  Tests if a bit is reset in number
    ///
    /// @param  number  Number to test
    /// @param  bit     Bit number to test
    ///
    /// @return TRUE if test passes.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsBitReset64(
        UINT64  number,
        UINT64  bit)
    {
        static const UINT64 One = 1;     /// @note Forces type of literal constant without relying on suffix

        CAMX_ASSERT(bit < (sizeof(UINT64) * 8));
        return ((number & (One << bit)) == 0) ? TRUE : FALSE;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsBitSet
    ///
    /// @brief  Tests if a bit is set in number
    ///
    /// @param  number  Number to test
    /// @param  bit     Bit number to test
    ///
    /// @return TRUE if test passes
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsBitSet(
        UINT32  number,
        UINT32  bit)
    {
        static const UINT32 One = 1;     /// @note Forces type of literal constant without relying on suffix

        CAMX_ASSERT(bit < (sizeof(UINT32) * 8));

        return ((number & (One << bit)) != 0) ? TRUE : FALSE;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsBitSet64
    ///
    /// @brief  Tests if a bit is set in number
    ///
    /// @param  number  Number to test
    /// @param  bit     Bit number to test
    ///
    /// @return TRUE if test passes
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsBitSet64(
        UINT64  number,
        UINT64  bit)
    {
        static const UINT64 One = 1;     /// @note Forces type of literal constant without relying on suffix

        CAMX_ASSERT(bit < (sizeof(UINT64) * 8));

        return ((number & (One << bit)) != 0) ? TRUE : FALSE;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsBitMaskSet64
    ///
    /// @brief  Tests if all bits set in mask are set in number
    ///
    /// @param  number  Number to test
    /// @param  mask    Bit mask
    ///
    /// @return TRUE if test passes
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsBitMaskSet64(
        UINT64  number,
        UINT64  mask)
    {
        return ((number & mask) == mask) ? TRUE : FALSE;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsBitMaskReset64
    ///
    /// @brief  Tests if all bits set in mask are reset in number
    ///
    /// @param  number  Number to test
    /// @param  mask    Bit mask
    ///
    /// @return TRUE if test passes
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE BOOL IsBitMaskReset64(
        UINT64  number,
        UINT64  mask)
    {
        return ((number & mask) == 0) ? TRUE : FALSE;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CountSetBits
    ///
    /// @brief  Counts the number of set bits present in the number.
    ///
    /// @param  number     UINT32 number
    ///
    /// @return number of set bits present in the number
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 CountSetBits(
        UINT32 number)
    {
        UINT32 numSetBits = 0;

#if defined (__GNUC__)
        numSetBits = __builtin_popcount(number);
#else
        numSetBits = number;
        // Add up the set bits.
        // The algorithm works by adding pairs of bit fields together iteratively,
        // where the size of each bit field doubles each time.
        // An example for an 8-bit value:
        // Bits:  h   g  f   e  d   c  b   a
        //         \ /    \ /    \ /    \ /
        // value = h+g    f+e    d+c    b+a
        //            \  /          \  /
        // value =   h+g+f+e       d+c+b+a
        //                  \     /
        // value =      h+g+f+e+d+c+b+a  ==> total number of set bits in the number
        numSetBits = ((numSetBits >> 1)  & 0x55555555) + (numSetBits & 0x55555555);
        numSetBits = ((numSetBits >> 2)  & 0x33333333) + (numSetBits & 0x33333333);
        numSetBits = ((numSetBits >> 4)  & 0x0f0f0f0f) + (numSetBits & 0x0f0f0f0f);
        numSetBits = ((numSetBits >> 8)  & 0x00ff00ff) + (numSetBits & 0x00ff00ff);
        numSetBits = ((numSetBits >> 16) & 0x0000ffff) + (numSetBits & 0x0000ffff);
#endif // defined(__GNUC__)

        return numSetBits;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FLOATToSFixed32
    ///
    /// @brief  Convert a floating point number to a signed fixed point number with the given fractional bits
    ///
    /// @param  floatVal            Number to convert
    /// @param  numFractionalBits   Number of fractional bits
    /// @param  round               Whether to enable rounding
    ///
    /// @return Signed 32-bit fixed point number representation of the input FLOAT
    ///
    /// @note   This function does not saturate on overflow
    ///         This function does not attempt to handle NaN
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static INT32 CAMX_INLINE FLOATToSFixed32(
        FLOAT   floatVal,
        UINT32  numFractionalBits,
        BOOL    round)
    {
        if (0 != numFractionalBits)
        {
            // Convert to integer scale
            floatVal *= (1u << numFractionalBits);
        }

        if (TRUE == round)
        {
            // Round before conversion
            floatVal += (0 < floatVal) ? 0.5f : -0.5f;
        }

        // Convert to fixed point
        return static_cast<INT32>(floatVal);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SFixed32ToFLOAT
    ///
    /// @brief  Convert a signed fixed point number to a floating point number with the given fractional bits
    ///
    /// @param  fixedPointNum       Number to convert
    /// @param  numFractionalBits   Number of fractional bits
    ///
    /// @return Floating point number representation of the input signed integer
    ///
    /// @note   This function does not saturate on overflow
    ///         This function does not attempt to handle NaN
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static FLOAT CAMX_INLINE SFixed32ToFLOAT(
        INT32   fixedPointNum,
        UINT32  numFractionalBits)
    {
        UINT32  integerValue;
        UINT32  fractionalBits;
        FLOAT   fractionalValue;
        UINT32  factor = (1u << numFractionalBits);

        // Calculate the integer portion of the result
        integerValue = (fixedPointNum >> numFractionalBits);
        // Get the bits representing the fractional portion
        fractionalBits = fixedPointNum & AllOnes32(numFractionalBits);
        // Calculate the fractional portion of the result
        fractionalValue = static_cast<FLOAT>(fractionalBits) / factor;

        return (integerValue + fractionalValue);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MaxFLOAT
    ///
    /// @brief  Returns the larger of the two input values.
    ///
    /// @param  value1  The first number to compare
    /// @param  value2  The second number to compare
    ///
    /// @return The larger of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static FLOAT CAMX_INLINE MaxFLOAT(
        FLOAT value1,
        FLOAT value2)
    {
        return ((value1 > value2) ? value1 : value2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MinFLOAT
    ///
    /// @brief  Returns the smaller of the two input values.
    ///
    /// @param  value1  The first number to compare
    /// @param  value2  The second number to compare
    ///
    /// @return The smaller of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static FLOAT CAMX_INLINE MinFLOAT(
        FLOAT value1,
        FLOAT value2)
    {
        return ((value1 < value2) ? value1 : value2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MaxUINT32
    ///
    /// @brief  Returns the larger of two UINT32 values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The larger of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT32 CAMX_INLINE MaxUINT32(
        UINT32 input1,
        UINT32 input2)
    {
        return ((input1 > input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MaxINT32
    ///
    /// @brief  Returns the larger of the two INT32 values.
    ///
    /// @param  value1  The first number to compare
    /// @param  value2  The second number to compare
    ///
    /// @return The larger of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT32 MaxINT32(
        INT32 value1,
        INT32 value2)
    {
        return ((value1 > value2) ? value1 : value2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MaxUINT16
    ///
    /// @brief  Returns the larger of two UINT16 values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The larger of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT16 CAMX_INLINE MaxUINT16(
        UINT16 input1,
        UINT16 input2)
    {
        return ((input1 > input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MinUINT16
    ///
    /// @brief  Returns the smaller of two UINT16 values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The smaller of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT16 CAMX_INLINE MinUINT16(
        UINT16 input1,
        UINT16 input2)
    {
        return ((input1 < input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FEqualCoarse
    ///
    /// @brief  Compares the floating point numbers with reduced precision
    ///
    /// @param  value1  The first number to compare
    /// @param  value2  The second number to compare
    ///
    /// @return BOOL TRUE if equal FALSE if not equal
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static  CAMX_INLINE BOOL FEqualCoarse(
        FLOAT value1, FLOAT value2)
    {
        return ((fabs(value1 - value2) < 1e-2) ? (TRUE) : (FALSE));
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MinUINT32
    ///
    /// @brief  Returns the smaller of two UINT32 values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The smaller of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT32 CAMX_INLINE MinUINT32(
        UINT32 input1,
        UINT32 input2)
    {
        return ((input1 < input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MinINT32
    ///
    /// @brief  Returns the smaller of two INT32 values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The smaller of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT32 CAMX_INLINE MinINT32(
        INT32 input1,
        INT32 input2)
    {
        return ((input1 < input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MinUINT64
    ///
    /// @brief  Returns the smaller of two UINT64 values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The smaller of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT64 CAMX_INLINE MinUINT64(
        UINT64 input1,
        UINT64 input2)
    {
        return ((input1 < input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MaxUINT64
    ///
    /// @brief  Returns the larger of two UINT64 values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The larger of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT64 CAMX_INLINE MaxUINT64(
        UINT64 input1,
        UINT64 input2)
    {
        return ((input1 > input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MinSIZET
    ///
    /// @brief  Returns the smaller of two SIZE_T values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The smaller of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static SIZE_T CAMX_INLINE MinSIZET(
        SIZE_T input1,
        SIZE_T input2)
    {
        return ((input1 < input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MaxSIZET
    ///
    /// @brief  Returns the larger of two SIZE_T values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The larger of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static SIZE_T CAMX_INLINE MaxSIZET(
        SIZE_T input1,
        SIZE_T input2)
    {
        return ((input1 > input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MinUINT
    ///
    /// @brief  Returns the smaller of two UINT values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The smaller of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT CAMX_INLINE MinUINT(
        UINT input1,
        UINT input2)
    {
        return ((input1 < input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MaxUINT
    ///
    /// @brief  Returns the larger of two UINT values
    ///
    /// @param  input1 The first number to compare
    /// @param  input2 The second number to compare
    ///
    /// @return The larger of the two input values
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT CAMX_INLINE MaxUINT(
        UINT input1,
        UINT input2)
    {
        return ((input1 > input2) ? input1 : input2);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// TwosComplementValidBits
    ///
    /// @brief  Get the 2's complement of the number with respect to valid bits.
    ///
    /// @param  value     value to be adjusted
    /// @param  validBits number of destination bits
    ///
    /// @return INT32     Adjusted value of valid bits
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT32 TwosComplementValidBits(
        INT32 value,
        UINT8 validBits)
    {
        if (value < 0)
        {
            value = -(value);
            value &= ((1 << validBits) - 1);
            value = (1 << validBits) - value;
        }
        else
        {
            value &= ((1 << validBits) - 1);
        }
        return value;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Memory Functions
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// VoidPtrInc
    ///
    /// @brief  Utility function to add the specified byte offset to a void pointer
    ///
    /// @param  pVoid       Pointer to be incremented
    /// @param  numBytes    Number of bytes to increase the pointer
    ///
    /// @return New pointer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID* VoidPtrInc(
        VOID*    pVoid,
        SIZE_T   numBytes)
    {
        return (static_cast<BYTE*>(pVoid) + numBytes);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ConstVoidPtrInc
    ///
    /// @brief  Utility function to add the specified byte offset to a void pointer (and deal with const-ness)
    ///
    /// @param  pVoid       Pointer to be incremented
    /// @param  numBytes    Number of bytes to increase the pointer
    ///
    /// @return New pointer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE const VOID* ConstVoidPtrInc(
        const VOID*  pVoid,
        SIZE_T       numBytes)
    {
        return (static_cast<const BYTE*>(pVoid) + numBytes);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// VoidPtrDec
    ///
    /// @brief  Utility function to subtract the specified byte offset from a void pointer
    ///
    /// @param  pVoid       Pointer to be decremented
    /// @param  numBytes    Number of bytes to decrease the pointer
    ///
    /// @return New pointer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID* VoidPtrDec(
        VOID*    pVoid,
        SIZE_T   numBytes)
    {
        return (static_cast<BYTE*>(pVoid) - numBytes);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ConstVoidPtrDec
    ///
    /// @brief  Utility function to subtract the specified byte offset from a void pointer (and deal with const-ness)
    ///
    /// @param  pVoid       Pointer to be decremented
    /// @param  numBytes    Number of bytes to decrease the pointer
    ///
    /// @return New pointer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE const VOID* ConstVoidPtrDec(
        const VOID*  pVoid,
        SIZE_T       numBytes)
    {
        return (static_cast<const BYTE*>(pVoid) - numBytes);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// VoidPtrToUINT64
    ///
    /// @brief  Utility function to store a void pointer in a UINT64 value, independent of actual pointer size
    ///
    /// @param  pVoid       Pointer to be stored
    ///
    /// @return UINT64 representation of the pointer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT64 VoidPtrToUINT64(
        VOID* pVoid)
    {
        return static_cast<UINT64>(reinterpret_cast<SIZE_T>(pVoid));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Memcmp
    ///
    /// @brief  Function to wrap the standard memcmp function; compares the first n bytes of memory between the two sources
    ///
    /// @param  pSrc1      pointer to first source
    /// @param  pSrc2      pointer to second source
    /// @param  numBytes   number of characters (bytes) to compare between pSrc1 and pSrc2
    ///
    /// @return An integer less than, equal to, or greater than zero if the first n bytes of s1 is found, respectively,
    ///         to be the same in relation to s2
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE INT Memcmp(
        const VOID*  pSrc1,
        const VOID*  pSrc2,
        SIZE_T       numBytes)
    {
        CAMX_ASSERT(pSrc1 != NULL);
        CAMX_ASSERT(pSrc2 != NULL);

        return memcmp(pSrc1, pSrc2, numBytes);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Memcpy
    ///
    /// @brief  Wraps the standard memcpy function; copies "numBytes" from source to destination
    ///
    /// @param  pDst       pointer to destination of copy
    /// @param  pSrc       pointer to source of copy
    /// @param  numBytes   size of data pointed at by pSrc
    ///
    /// @return Dest Pointer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID* Memcpy(
        VOID*       pDst,
        const VOID* pSrc,
        SIZE_T      numBytes)
    {
        CAMX_ASSERT(pDst != NULL);
        CAMX_ASSERT(pSrc != NULL);

        return memcpy(pDst, pSrc, numBytes);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Memmove
    ///
    /// @brief  Wraps the standard Memmove function; moves "numBytes" from source to destination
    ///
    /// @param  pDst       pointer to destination of move
    /// @param  pSrc       pointer to source of move
    /// @param  numBytes   size of data pointed at by pSrc
    ///
    /// @return Dest Pointer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID* Memmove(
        VOID*       pDst,
        const VOID* pSrc,
        SIZE_T      numBytes)
    {
        CAMX_ASSERT(pDst != NULL);
        CAMX_ASSERT(pSrc != NULL);

        return memmove(pDst, pSrc, numBytes);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Memset
    ///
    /// @brief  Wraps the standard memset function; sets "numBytes" at the destination pointer to the specified pattern
    ///
    /// @param  pDst        pointer to destination of copy
    /// @param  setVal      character valueto set
    /// @param  numBytes    number of characters (bytes) to copy from pSrc to pDst
    ///
    /// @return Destination pointer
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID* Memset(
        VOID*    pDst,
        INT      setVal,
        SIZE_T   numBytes)
    {
        CAMX_ASSERT(pDst != NULL);
        return memset(pDst, setVal, numBytes);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AllOnes32
    ///
    /// @brief  Returns a bitmask with all 'numberOfBits' LSB bits set
    ///
    /// @param  numberOfBits  Number of LSB bits to set in the bit-mask
    ///
    /// @return 32 bit bitmask of 1's with all 'numberOfBits' LSB bits set
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 AllOnes32(
        UINT32 numberOfBits)
    {
        CAMX_ASSERT(numberOfBits <= 32);

        return (1 << numberOfBits) - 1;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AllOnes32LeftShift
    ///
    /// @brief  Left shift the result of AllOnes32
    ///
    /// @param  numberOfBits    Number of LSB bits to set in the mask before shifting the mask to the left
    /// @param  leftShiftBits   The number of bits to shift left
    ///
    /// @return the result of AllOnes32 left-shifted by leftShiftBits
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT32 AllOnes32LeftShift(
        UINT32 numberOfBits,
        UINT32 leftShiftBits)
    {
        CAMX_ASSERT(numberOfBits <= 32);
        CAMX_ASSERT(leftShiftBits <= 32);
        return ((1 << numberOfBits) - 1) << leftShiftBits;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AllOnes64
    ///
    /// @brief  Returns a bitmask with all 'numberOfBits' LSB bits set
    ///
    /// @param  numberOfBits  Number of LSB bits to set in the bit-mask
    ///
    /// @return 64 bit bitmask of 1's with all 'numberOfBits' LSB bits set
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT64 AllOnes64(
        UINT32 numberOfBits)
    {
        CAMX_ASSERT(numberOfBits <= 64);

        return (1ULL << numberOfBits) - 1ULL;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AllOnes64LeftShift
    ///
    /// @brief  Left shift the result of AllOnes64
    ///
    /// @param  numberOfBits    Number of LSB bits to set in the mask before shifting the mask to the left
    /// @param  leftShiftBits   The number of bits to shift left
    ///
    /// @return the result of AllOnes64 left-shifted by leftShiftBits
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE UINT64 AllOnes64LeftShift(
        UINT32 numberOfBits,
        UINT32 leftShiftBits)
    {
        CAMX_ASSERT(numberOfBits <= 32);
        CAMX_ASSERT(leftShiftBits <= 32);
        return ((1ULL << numberOfBits) - 1ULL) << leftShiftBits;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Srand
    ///
    /// @brief  Initialize pseudo-random number generator. To generate different sequences of results by calling rand(), a
    ///         different seed should be used, such as time value.
    ///
    /// @param  seed    Used to initialize the random number generator to allow distinctive sequences of results from rand().
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID Srand(
        UINT seed)
    {
        return srand(seed);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Rand
    ///
    /// @brief  Generate a random floating point number between 0 and 1.
    ///
    /// @return FLOAT
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE FLOAT Rand()
    {
        return (static_cast<FLOAT>(rand()) / static_cast<FLOAT>(RAND_MAX));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Qsort
    ///
    /// @brief  Wraps the standard qsort function; sorts "num" elements of "base" using function "compar"
    ///
    /// @param  base   Pointer to the first object of the array to be sorted, converted to a void*.
    /// @param  num    Number of elements in the array pointed to by base.
    /// @param  size   Size in bytes of each element in the array.
    /// @param  compare Pointer to a function that compares two elements.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID Qsort(
        VOID*  pBase,
        SIZE_T num,
        SIZE_T size,
        INT    (*pCompare)(const VOID*, const VOID*))
    {
        CAMX_ASSERT(NULL != pBase);
        CAMX_ASSERT(NULL != pCompare);

        qsort(pBase, num, size, pCompare);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FEqual
    ///
    /// @brief  Compares the floating point numbers
    ///
    /// @param  value1  The first number to compare
    /// @param  value2  The second number to compare
    ///
    /// @return BOOL TRUE if equal FALSE if not equal
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static  CAMX_INLINE BOOL FEqual(
        FLOAT value1, FLOAT value2)
    {
        return ((fabs(value1 - value2) < 1e-9) ? (TRUE) : (FALSE));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CalculateShiftBits
    ///
    /// @brief  Calculate the shift bits required to produce output of specified depth.
    ///
    /// @param  pixels          Number of pixels to calculate shift bits for
    /// @param  inputDepth      Bit depth of input
    /// @param  outputDepth     Bit depth of output
    ///
    /// @return shift bits required to get output of specified bit depth
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT32 CalculateShiftBits(
        UINT32  pixels,
        UINT32  inputDepth,
        UINT32  outputDepth)
    {
        UINT32  shiftBits           = 0;
        UINT32  numberOfBits        = 0;
        INT32   bithDepthDifference = outputDepth - inputDepth;

        numberOfBits = MinBitsUINT32(pixels);
        if (static_cast<INT32>(numberOfBits) > bithDepthDifference)
        {
            shiftBits = numberOfBits - bithDepthDifference;
        }
        else
        {
            shiftBits = 0;
        }

        return shiftBits;
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FloatToQNumber
    ///
    /// @brief  Converts Float value to Q Format
    ///
    /// @param  value   Float Value , for which Needs to converted to Q format
    /// @param  QNumber constant value to be used for conversion of float to Q
    ///
    /// @return INT32 The converted value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static __inline INT32 FloatToQNumber(
        FLOAT value,
        INT QNumber)
    {
        return  RoundFLOAT((value * static_cast<FLOAT>(QNumber)));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SignExtendQnumber
    ///
    /// @brief  Sign extends Q number
    ///
    /// @param  value     int Value , Q number value which needs sign extension
    /// @param  validBits valid bits in value
    ///
    /// @return INT  sign extended Qnumber
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static __inline INT SignExtendQnumber(
        INT value,
        INT validBits)
    {
        INT ret = value;
        if (value & (1 << (validBits - 1)))
        {
            ret = (((INT) ~ 0) ^ ((1 << validBits) - 1)) | value;
        }
        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DoubleToQNumber
    ///
    /// @brief  Converts Double value to Q Format
    ///
    /// @param  value   Double Value , for which Needs to converted to Q format
    /// @param  QNumber constant value to be used for conversion of double to Q
    ///
    /// @return INT32 The converted value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static __inline INT32 DoubleToQNumber(
        DOUBLE value,
        INT QNumber)
    {
        return static_cast<INT32>(RoundDOUBLE((value * static_cast<DOUBLE>(QNumber))));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FloatToHalf
    ///
    /// @brief  Converts Float value to half float
    ///
    /// @param  f      Float Value to be converted to half float
    ///
    /// @return UINT16 The converted value
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT16 FloatToHalf(
        FLOAT f)
    {
        // For IEEE-754 float representation, the sign is in bit 31, biased exponent is in bits 23-30 and mantissa is in bits
        // 0-22. Using hex representation, extract sign, biased exponent and mantissa.
        UINT32 hex_32             = *(reinterpret_cast<UINT32*>(&f));
        UINT32 sign_32            = hex_32 & (0x80000000);
        UINT32 biased_exponent_32 = hex_32 & (0x7F800000);
        UINT32 mantissa_32        = hex_32 & (0x007FFFFF);

        // special case: 0 or denorm
        if (biased_exponent_32 == 0)
        {
            return 0;
        }

        // The exponent is stored in the range 1 .. 254 (0 and 255 have special meanings), and is biased by subtracting 127
        // to get an exponent value in the range -126 .. +127.
        // remove exp bias, adjust mantissa
        INT32 exponent_32 = (static_cast<INT32>(hex_32 >> 23)) - 127;
        mantissa_32 = ((mantissa_32 >> (23 - 10 - 1)) + 1) >> 1;    // shift with rounding to yield 10 MSBs

        if (mantissa_32 & 0x00000400)
        {
            mantissa_32 >>= 1;  // rounding resulted in overflow, so adjust mantissa and exponent
            exponent_32++;
        }

        // Can only support 4 bits for exponent with half
        CAMX_ASSERT(exponent_32 <= 15 && exponent_32 >= -14);

        // compose
        UINT16 sign_16            = static_cast<UINT16>(sign_32 >> 16);
        UINT16 biased_exponent_16 = static_cast<UINT16>((exponent_32 + 15) << 10);
        UINT16 mantissa_16        = static_cast<UINT16>(mantissa_32);

        return (sign_16 | biased_exponent_16 | mantissa_16);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// MatchAspectRatio
    ///
    /// @brief  Matches output dimensions aspect ratio to reference dimensions aspect ratio
    ///
    /// @param  pReferenceDimension     Pointer to reference dimension
    /// @param  pUpdateDimension        Pointer to dimension that needs to be updated
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID MatchAspectRatio(
        const CamxDimension* pReferenceDimension,
        CamxDimension*       pUpdateDimension)
    {
        FLOAT referenceAspectRatio = 0.0f;
        FLOAT currentAspectRatio   = 0.0f;

        CAMX_ASSERT(pReferenceDimension != NULL);
        CAMX_ASSERT(pUpdateDimension != NULL);

        referenceAspectRatio = static_cast<FLOAT>(pReferenceDimension->width) / static_cast<FLOAT>(pReferenceDimension->height);
        currentAspectRatio   = static_cast<FLOAT>(pUpdateDimension->width) / static_cast<FLOAT>(pUpdateDimension->height);

        if (currentAspectRatio < referenceAspectRatio)
        {
            pUpdateDimension->height = static_cast<UINT32>(static_cast<FLOAT>(pUpdateDimension->width) / referenceAspectRatio);
        }
        else if (currentAspectRatio > referenceAspectRatio)
        {
            pUpdateDimension->width = static_cast<UINT32>(static_cast<FLOAT>(pUpdateDimension->height) * referenceAspectRatio);
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CalculateLCM
    ///
    /// @brief  Calculate the Least Common Multiple of the two input data
    ///
    /// @param  value0  First value to compare for LCM
    /// @param  value1  Second value to compare for LCM
    ///
    /// @return INT32 The Least Common Multiple
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static INT32 CalculateLCM(
        INT32 value0,
        INT32 value1)
    {
        INT32 leastCommonMultiple = 0;
        BOOL  foundLCM            = FALSE;

        value0 = Utils::AbsoluteINT32(value0);
        value1 = Utils::AbsoluteINT32(value1);

        if ((0 != value0) && (0 != value1))
        {

            if (value0 != value1)
            {
                INT32 maxValue = Utils::MaxUINT32(value0, value1);
                INT32 minValue = Utils::MinUINT32(value0, value1);

                leastCommonMultiple = maxValue;

                while (FALSE == foundLCM)
                {
                    if (0 == leastCommonMultiple % minValue)
                    {
                        foundLCM = TRUE;
                    }
                    else
                    {
                        leastCommonMultiple += maxValue;
                    }
                }
            }
            else
            {
                leastCommonMultiple = value0;
            }
        }
        else if (0 == value0)
        {
            leastCommonMultiple = value1;
        }
        else
        {
            leastCommonMultiple = value0;
        }

        return leastCommonMultiple;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FindAlignment
    ///
    /// @brief  Find the binary alignment of a given input number.
    ///         In essence, this function find the LSB bit position that
    ///         is set in a given input number and returns its alignment.
    ///         I.e., for 6, the return value will be 2 (b00000110 => b00000010)
    ///
    /// @param  value  Number to for which to find alignment.
    ///
    /// @return UINT32 The byte alignment for this number. Returns 1 if number is 0
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT32 FindAlignment(
        UINT32 value)
    {
        UINT32 alignment = 0;

        while ((0 != value) && ((value & 1) == 0))
        {
            alignment++;
            value = value >> 1;
        }

        return 1 << alignment;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CalculateAlignment
    ///
    /// @brief  Calculate the Nearest Alignment of two input numbers.
    ///         This function finds that smallest number that can contain
    ///         both of the provided inputs and maintain the highest binary
    ///         bit alignment between them.
    ///         To do this, it first finds the highest number between them and
    ///         and then aligns that number to highest input alignment.
    ///         For instance, when provided with the numbers 68 and 32 it will
    ///         execute the following:
    ///         1) Find the highest number    = 68.
    ///         2) Find the highest alignment = 32  (68 = b01001000, 32 = b00100000)
    ///         3) Align the highest number to the highest binary alignment:
    ///            (68 + 31) & ~(31) = 96
    ///
    /// @param  value0  First value to compare for alignment
    /// @param  value1  Second value to compare for alignment
    ///
    /// @return UINT32 Nearest alignment - highest value aligned to the highest bit alignment
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT32 CalculateAlignment(
        UINT32 value0,
        UINT32 value1)
    {
        UINT32 alignedValue = 0;

        if ((0 != value0) && (0 != value1))
        {
            if (value0 != value1)
            {
                UINT32 maxValue = Utils::MaxUINT32(value0, value1);
                UINT32 alignment = Utils::MaxUINT32(FindAlignment(value0), FindAlignment(value1));

                alignedValue = ((maxValue + (alignment - 1)) & ~(alignment - 1));
            }
            else
            {
                alignedValue = value0;
            }
        }
        else if (0 == value0)
        {
            alignedValue = value1;
        }
        else
        {
            alignedValue = value0;
        }

        return alignedValue;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SearchElementInUnsortedArray
    ///
    /// @brief  Search the input unsorted array to find whether the given value exits or not
    ///
    /// @param  pArray              Input Array which needs to be searched whether the given search element present in this.
    /// @param  numElementsInArray  Number of elements in array.
    /// @param  elementToSearch     Value to search in the given input array.
    ///
    /// @return TRUE if element exists in input array
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static BOOL SearchElementInUnsortedArray(
        const INT32*    pArray,
        const UINT      numElementsInArray,
        INT32           elementToSearch)
    {
        BOOL bExists = FALSE;

        CAMX_ASSERT(NULL != pArray);

        for (UINT i = 0; i < numElementsInArray; i++)
        {
            if (pArray[i] == elementToSearch)
            {
                bExists = TRUE;
                break;
            }
        }

        return bExists;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsArray1SubsetOfArray2
    ///
    /// @brief  Find whether all the elements in Array1 present in Array2
    ///
    /// @param  pArray1                 Array of elements which needs to be checked whether all the elements in this present
    ///                                 in Array2
    /// @param  numElementsInArray1     Number of elements in Array1.
    /// @param  pArray2                 Array in which search has to be performed to check whether all the elements in Arra1
    ///                                 are present in this Array2
    /// @param  numElementsInArray2     Number of elements in Array2
    ///
    /// @return TRUE if all elements in Array1 present in Array2
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static BOOL IsArray1SubsetOfArray2(
        const INT32* pArray1,
        const UINT   numElementsInArray1,
        const INT32* pArray2,
        const UINT   numElementsInArray2)
    {
        // Start with TRUE, as we want to treat empty Array1 as subset of Array2
        BOOL bIsSubset = TRUE;

        CAMX_ASSERT(NULL != pArray1);
        CAMX_ASSERT(NULL != pArray2);

        for (UINT i = 0; i < numElementsInArray1; i++)
        {
            if (FALSE == SearchElementInUnsortedArray(pArray2, numElementsInArray2, pArray1[i]))
            {
                bIsSubset = FALSE;
                break;
            }
        }

        return bIsSubset;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FindElementsInArray1NotPresentInArray2
    ///
    /// @brief  Find elements of Array1 that are not present in Array2
    ///
    /// @param  pArray1                 Array of elements which needs to be checked whether all the elements in this present
    ///                                 in Array2
    /// @param  numElementsInArray1     Number of elements in Array1
    /// @param  pArray2                 Array in which search has to be performed to check whether all the elements in Arra1 are
    ///                                 present in this Array
    /// @param  numElementsInArray2     Number of elements in Array2
    /// @param  pResultArray            Results array to store elements of Array1 that are not present in Array2
    /// @param  sizeofResultArray       Size of pNotPresentElementsArray.
    ///
    /// @return Number of elements saved in pNotPresentElementsArray
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT FindElementsInArray1NotPresentInArray2(
        const INT32* pArray1,
        const UINT   numElementsInArray1,
        const INT32* pArray2,
        const UINT   numElementsInArray2,
        INT32*       pResultArray,
        const UINT   sizeofResultArray)
    {
        UINT numElementsAdded = 0;

        CAMX_ASSERT(NULL != pArray1);
        CAMX_ASSERT(NULL != pArray2);
        CAMX_ASSERT(NULL != pResultArray);

        for (UINT i = 0; (i < numElementsInArray1) && (numElementsAdded < sizeofResultArray); i++)
        {
            if (FALSE == SearchElementInUnsortedArray(pArray2, numElementsInArray2, pArray1[i]))
            {
                pResultArray[numElementsAdded++] = pArray1[i];
            }
        }

        return numElementsAdded;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AppendArray1ToArray2
    ///
    /// @brief  Find elements in Array1 that are not present in Array2 and add them into Array2
    ///
    /// @param  pArray1                 Array of elements which needs to be checked whether all the elements in this present
    ///                                 in Array2
    /// @param  numElementsInArray1     Number of elements in Array1
    /// @param  pArray2                 Array in which search has to be performed to check whether all the elements in Arra1 are
    ///                                 present in this Array
    /// @param  numElementsInArray2     Number of elements in Array2
    /// @param  sizeofArray2            Size of Array2
    ///
    /// @return Number of elements saved in pAppendInArray
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT AppendArray1ToArray2(
        const INT32* pArray1,
        const UINT   numElementsInArray1,
        INT32*       pArray2,
        UINT         numElementsInArray2,
        const UINT   sizeofArray2)
    {
        UINT numElementsAdded = 0;

        CAMX_ASSERT(NULL != pArray1);
        CAMX_ASSERT(NULL != pArray2);

        for (UINT i = 0; (i < numElementsInArray1) && (numElementsInArray2 < sizeofArray2); i++)
        {
            if (FALSE == SearchElementInUnsortedArray(pArray2, numElementsInArray2, pArray1[i]))
            {
                pArray2[numElementsInArray2++] = pArray1[i];
                numElementsAdded++;
            }
        }

        return numElementsAdded;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FindClosestIndex
    ///
    /// @brief  Find the closest index by comparing the values at the neighbor index's values of an array
    ///
    /// @param  valueAtLowIndex     Value at the low index
    /// @param  valueAtHighIndex    Value at the high index
    /// @param  searchValue         Value to be searched
    /// @param  highIndex           higher index value.
    ///
    /// @return UINT Position of the closest integer.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT FindClosestIndex(
        INT  valueAtLowIndex,
        INT  valueAtHighIndex,
        INT  searchValue,
        UINT highIndex)
    {
        UINT index = 0;

        if (abs(abs(searchValue) - abs(valueAtLowIndex)) > (abs(searchValue) - abs(valueAtHighIndex)))
        {
            index = highIndex;
        }
        else
        {
            index = (highIndex - 1);
        }

        return index;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FindClosestInAscendingSortedIntArray
    ///
    /// @brief  Find the closest integer position index in the integer array sorted in ascending order
    ///
    /// @param  pArray  pointer to array in which the the search needs to be performed
    /// @param  size    Size of the array
    /// @param  value   Value to be searched
    ///
    /// @return UINT Position of the closest integer.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT FindClosestInAscendingSortedIntArray(
        const INT16* pArray,
        UINT         size,
        INT          value)
    {
        UINT start  = 0;
        UINT end    = size - 1;
        UINT mid    = 0;
        UINT index  = 0;

        if (value <= pArray[0])
        {
            index = start;
        }
        else if (value >= pArray[end])
        {
            index = end;
        }
        else
        {
            while (start < end)
            {
                mid = (start + end) / 2;
                if (value == pArray[mid])
                {
                    index = mid;
                    break;
                }
                else if (value < pArray[mid])
                {
                    if ((mid > 0) && (value > pArray[mid - 1]))
                    {
                        index = FindClosestIndex(pArray[mid - 1], pArray[mid], value, mid);
                        break;
                    }

                    end = mid;
                }
                else
                {
                    if ((mid < (size -1)) && (value < pArray[mid + 1]))
                    {
                        index = FindClosestIndex(pArray[mid], pArray[mid + 1], value, (mid + 1));
                        break;
                    }

                    start = (mid + 1);
                }
            }
        }

        return index;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FindClosestInDescendingSortedIntArray
    ///
    /// @brief  Find the closest integer position index in the integer array sorted in descending order
    ///
    /// @param  pArray  pointer to array in which the the search needs to be performed
    /// @param  size    Size of the array
    /// @param  value   Value to be searched
    ///
    /// @return UINT Position of the closest integer.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT FindClosestInDescendingSortedIntArray(
        const INT16* pArray,
        UINT         size,
        INT          value)
    {
        UINT start  = 0;
        UINT end    = size -1;
        UINT mid    = 0;
        UINT index  = 0;

        if (value >= pArray[0])
        {
            index = start;
        }
        else if (value <= pArray[end])
        {
            index = end;
        }
        else
        {
            while (start < end)
            {
                mid = (start + end) / 2;
                if (value == pArray[mid])
                {
                    index = mid;
                    break;
                }
                else if (value > pArray[mid])
                {
                    if ((mid > 0) && (value < pArray[mid - 1]))
                    {
                        index = FindClosestIndex(pArray[mid - 1], pArray[mid], value, mid);
                        break;
                    }

                    end = mid;
                }
                else
                {
                    if ((mid < (size -1)) && (value > pArray[mid + 1]))
                    {
                        index = FindClosestIndex(pArray[mid], pArray[mid + 1], value, (mid + 1));
                        break;
                    }

                    start = (mid + 1);
                }
            }
        }

        return index;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CamxResultExtToString
    ///
    /// @brief  Converts a CamxResult Ext result code to a string represents the error
    ///
    /// @param  result              The CamxResult result code to convert
    /// @param  rpResultString      The Resulted String to return.
    /// @param  rpResultDescription Description of the error message.
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE VOID CamxResultExtToString(
        CamxResult      result,
        const CHAR*&    rpResultString,
        const CHAR*&    rpResultDescription)
    {
        switch (result)
        {
            case CamxResultExtCoreInvalidReqAccess:
                rpResultString      = "CamxResultExtCoreInvalidReqAccess";
                rpResultDescription = "Description: Camx Result Ext Core Invalid Req Access";
                break;
            case CamxResultExtCoreSOFWatchDogTimeout:
                rpResultString      = "CamxResultExtCoreSOFWatchDogTimeout";
                rpResultDescription = "Description: CamxResultExt Core SOF WatchDog Timeout";
                break;
            case CamxResultExtCoreResultTimedOut:
                rpResultString      = "CamxResultExtCoreResultTimedOut";
                rpResultDescription = "Description: CamxResultExt Core Result TimedOut";
                break;
            case CamxResultExtCoreFlushResultTimedOut:
                rpResultString      = "CamxResultExtCoreFlushResultTimedOut";
                rpResultDescription = "Description: CamxResultExt Core Flush Result TimedOut";
                break;
            case CamxResultExtCorePCRTimeout:
                rpResultString      = "CamxResultExtCorePCRTimeout";
                rpResultDescription = "Description: CamxResultExt Core PCR Timeout";
                break;
            case CamxResultExtCoreHWEnvInitFail:
                rpResultString      = "CamxResultExtCoreHWEnvInitFail";
                rpResultDescription = "Description: CamxResultExt Core HWEnv Init Fail";
                break;
            case CamxResultExtCoreReqSubmitTwice:
                rpResultString      = "CamxResultExtCoreReqSubmitTwice";
                rpResultDescription = "Description: CamxResultExt Core Req Submit Twice";
                break;
            case CamxResultExtCoreShutterError:
                rpResultString      = "CamxResultExtCoreShutterError";
                rpResultDescription = "Description: CamxResultExt Core Shutter Error";
                break;
            case CamxResultExtCorePipelineFlushTimeOut:
                rpResultString      = "CamxResultExtCorePipelineFlushTimeOut";
                rpResultDescription = "Description: CamxResultExt Core Pipeline Flush TimeOut";
                break;
            case CamxResultExtCoreSessionFlushTimeOut:
                rpResultString      = "CamxResultExtCoreSessionFlushTimeOut";
                rpResultDescription = "Description: CamxResultExt Core Session Flush TimeOut";
                break;
            case CamxResultExtCorePreemptTimeout:
                rpResultString      = "CamxResultExtCorePreemptTimeout";
                rpResultDescription = "Description: CamxResultExt Core WaitAllNodeRequestsDone for StreamOff Timeout";
                break;

            // Kernel extended error codes (Starts from 512)

            case CamxResultExtKMDRecovery:
                rpResultString      = "CamxResultExtKMDRecovery";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtKMDFullRecovery:
                rpResultString      = "CamxResultExtKMDFullRecovery";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtKMDSOFFreeze:
                rpResultString      = "CamxResultExtKMDSOFFreeze";
                rpResultDescription = "Description: ";
                break;

            // IFE extended error codes (Starts from 768)

            case CamxResultExtIFEUnsupportedHDRFormat:
                rpResultString      = "CamxResultExtIFEUnsupportedHDRFormat";
                rpResultDescription = "Description: ";
                break;

            // IPE extended error codes (Starts from 1024)

            case CamxResultExtIPEInvalidBWVote:
                rpResultString      = "CamxResultExtIPEInvalidBWVote";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidDimension:
                rpResultString      = "CamxResultExtIPEInvalidDimension";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidFormat:
                rpResultString      = "CamxResultExtIPEInvalidFormat";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEIQModuleFail:
                rpResultString      = "CamxResultExtIPEIQModuleFail";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidTuningData:
                rpResultString      = "CamxResultExtIPEInvalidTuningData";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidCropRegion:
                rpResultString      = "CamxResultExtIPEInvalidCropRegion";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEAcquireFailure:
                rpResultString      = "CamxResultExtIPEAcquireFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEMAPFailure:
                rpResultString      = "CamxResultExtIPEMAPFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInputError:
                rpResultString      = "CamxResultExtIPEInputError";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEHWTimeOut:
                rpResultString      = "CamxResultExtIPEHWTimeOut";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEStripingFailure:
                rpResultString      = "CamxResultExtIPEStripingFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEPassError:
                rpResultString      = "CamxResultExtIPEPassError";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidStats:
                rpResultString      = "CamxResultExtIPEInvalidStats";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEBufferAllocFailure:
                rpResultString      = "CamxResultExtIPEBufferAllocFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEPatchingFailure:
                rpResultString      = "CamxResultExtIPEPatchingFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidInputMeta:
                rpResultString      = "CamxResultExtIPEInvalidInputMeta";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidInputFences:
                rpResultString      = "CamxResultExtIPEInvalidInputFences";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidConfiguration:
                rpResultString      = "CamxResultExtIPEInvalidConfiguration";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEGeoLibError:
                rpResultString      = "CamxResultExtIPEGeoLibError";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPENCLibError:
                rpResultString      = "CamxResultExtIPENCLibError";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEPerModError:
                rpResultString      = "CamxResultExtIPEPerModError";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPECMDBufNoMemory:
                rpResultString      = "CamxResultExtIPECMDBufNoMemory";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidCmdBuffer:
                rpResultString      = "CamxResultExtIPEInvalidCmdBuffer";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidPortConfig:
                rpResultString      = "CamxResultExtIPEInvalidPortConfig";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidImageBuffer:
                rpResultString      = "CamxResultExtIPEInvalidImageBuffer";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEInvalidIOConfig:
                rpResultString      = "CamxResultExtIPEInvalidIOConfig";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPEIQModuleCreateFailure:
                rpResultString      = "CamxResultExtIPEIQModuleCreateFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIPECmdBufCreateFailure:
                rpResultString      = "CamxResultExtIPECmdBufCreateFailure";
                rpResultDescription = "Description: ";
                break;

            // BPS extended error codes (Starts from 1280)

            case CamxResultExtBPSInvalidBWVote:
                rpResultString      = "CamxResultExtBPSInvalidBWVote";
                rpResultDescription = "Description: ";
                break;

            // CVP extended error codes (Starts from 1536)

            case CamxResultExtCVPSSRError:
                rpResultString      = "CamxResultExtCVPSSRError";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPSesCreationFailed:
                rpResultString      = "CamxResultExtCVPSesCreationFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPSesInitFailed:
                rpResultString      = "CamxResultExtCVPSesInitFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPSesStartFailed:
                rpResultString      = "CamxResultExtCVPSesStartFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPSesDestroyFailed:
                rpResultString      = "CamxResultExtCVPSesDestroyFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPSesDeinitFailed:
                rpResultString      = "CamxResultExtCVPSesDeinitFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPSesStopFailed:
                rpResultString      = "CamxResultExtCVPSesStopFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPDMEExecFailed:
                rpResultString      = "CamxResultExtCVPDMEExecFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPOutputValdtnFailed:
                rpResultString      = "CamxResultExtCVPOutputValdtnFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtCVPOutputNCLIBFailed:
                rpResultString      = "CamxResultExtCVPOutputNCLIBFailed";
                rpResultDescription = "Description: ";
                break;

            // QSAT extended error codes (Starts from 1792)

            case CamxResultExtQSATSSRError:
                rpResultString      = "CamxResultExtQSATSSRError";
                rpResultDescription = "Description: ";
                break;

            // FD extended error codes (Starts from 2048)
            case CamxResultExtFDBase:
                rpResultString      = "CamxResultExtFDBase";
                rpResultDescription = "Description: ";
                break;

            // JPEG extended error codes (Starts from 2304)
            case CamxResultExtJPEGBase:
                rpResultString      = "CamxResultExtJPEGBase";
                rpResultDescription = "Description: ";
                break;

            // StatsParser extended error codes (Starts from 2560)
            case CamxResultExtStatsParseBase:
                rpResultString      = "CamxResultExtStatsParseBase";
                rpResultDescription = "Description: ";
                break;

            // AEC extended error codes (Starts from 3072)
            case CamxResultExtAECBase:
                rpResultString      = "CamxResultExtAECBase";
                rpResultDescription = "Description: ";
                break;

            // AWB extended error codes (Starts from 3328)
            case CamxResultExtAWBBase:
                rpResultString      = "CamxResultExtAWBBase";
                rpResultDescription = "Description: ";
                break;

            // AF extended error codes (Starts from 3584)
            case CamxResultExtAFBase:
                rpResultString      = "CamxResultExtAFBase";
                rpResultDescription = "Description: ";
                break;

            // ASD extended error codes (Starts from 3840)
            case CamxResultExtASDBase:
                rpResultString      = "CamxResultExtASDBase";
                rpResultDescription = "Description: ";
                break;

            // AFD extended error codes (Starts from 4096)
            case CamxResultExtAFDBase:
                rpResultString      = "CamxResultExtAFDBase";
                rpResultDescription = "Description: ";
                break;

            // EIS extended error codes (Starts from 4352)
            case CamxResultExtEISInitFailure:
                rpResultString      = "CamxResultExtEISInitFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtEISNCSFailure:
                rpResultString      = "CamxResultExtEISNCSFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtEISDepFailure:
                rpResultString      = "CamxResultExtEISDepFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtEISCropFailure:
                rpResultString      = "CamxResultExtEISCropFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtEISAlgoFailure:
                rpResultString      = "CamxResultExtEISAlgoFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtEISSampleWindow:
                rpResultString      = "CamxResultExtEISSampleWindow";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtEISMarginFailure:
                rpResultString      = "CamxResultExtEISMarginFailure";
                rpResultDescription = "Description: ";
                break;

            // IQModule extended error codes (Starts from 4608)
            case CamxResultExtIQModInterpolationFailed:
                rpResultString      = "CamxResultExtIQModInterpolationFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIQModCalcSettingFailed:
                rpResultString      = "CamxResultExtIQModCalcSettingFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIQModPackRegisterFailed:
                rpResultString      = "CamxResultExtIQModPackRegisterFailed";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIQModChromatixFailure:
                rpResultString      = "CamxResultExtIQModChromatixFailure";
                rpResultDescription = "Description: ";
                break;
            case CamxResultExtIQModGetCmdBufferFailure:
                rpResultString      = "CamxResultExtIQModGetCmdBufferFailure";
                rpResultDescription = "Description: ";
                break;

            // Fence error reason types
            case CamxResultExtCommonFenceUnused:
                rpResultString = "CamxResultExtCommonFenceUnused";
                rpResultDescription = "Description: CamxResultExt Common Fence Unused";
                break;
            case CamxResultExtCommonFenceSuccess:
                rpResultString = "CamxResultExtCommonFenceSuccess";
                rpResultDescription = "Description: CamxResultExt Common Fence Success";
                break;
            case CamxResultExtCommonFenceFlush:
                rpResultString = "CamxResultExtGenFenceFlush";
                rpResultDescription = "Description: CamxResultExt Common Fence Flush";
                break;
            case CamxResultExtCommonFenceStop:
                rpResultString = "CamxResultExtGenFenceStop";
                rpResultDescription = "Description: CamxResultExt Common Fence Stop";
                break;
            case CamxResultExtCommonFenceSynx:
                rpResultString = "CamxResultExtGenFenceSynx";
                rpResultDescription = "Description: CamxResultExt Common Fence Synx";
                break;
            case CamxResultExtCommonFenceRegPayload:
                rpResultString = "CamxResultExtCommonFenceRegPayload";
                rpResultDescription = "Description: CamxResultExt Common Fence Register Payload";
                break;
            case CamxResultExtCommonFenceSyncSignal:
                rpResultString = "CamxResultExtCommonFenceSyncSignal";
                rpResultDescription = "Description: CamxResultExt Common Fence Sync Signal";
                break;
            case CamxResultExtCommonFenceRelease:
                rpResultString = "CamxResultExtCommonFenceRelease";
                rpResultDescription = "Description: CamxResultExt Common Fence Release";
                break;

            // Isp error reason types
            case CamxResultExtIspErrorUnknown:
                rpResultString = "CamxResultExtIspErrorUnknown";
                rpResultDescription = "Description: CamxResultExt Isp Error Unknown";
                break;
            case CamxResultExtIspErrorBubble:
                rpResultString = "CamxResultExtIspErrorBubble";
                rpResultDescription = "Description: CamxResultExt Isp Error Bubble";
                break;
            case CamxResultExtIspErrorOverflow:
                rpResultString = "CamxResultExtIspErrorOverflow";
                rpResultDescription = "Description: CamxResultExt Isp Error Overflow";
                break;
            case CamxResultExtIspErrorP2iError:
                rpResultString = "CamxResultExtIspErrorP2iError";
                rpResultDescription = "Description: CamxResultExt Isp Error P2iError";
                break;
            case CamxResultExtIspErrorViolation:
                rpResultString = "CamxResultExtIspErrorViolation";
                rpResultDescription = "Description: CamxResultExt Isp Error Violation";
                break;
            case CamxResultExtIspErrorBusifOverflow:
                rpResultString = "CamxResultExtIspErrorBusifOverflow";
                rpResultDescription = "Description: CamxResultExt Isp Error Busif Overflow";
                break;
            case CamxResultExtIspErrorFlush:
                rpResultString = "CamxResultExtIspErrorFlush";
                rpResultDescription = "Description: CamxResultExt Isp Error Flush";
                break;
            case CamxResultExtIspErrorHwStop:
                rpResultString = "CamxResultExtIspErrorHwStop";
                rpResultDescription = "Description: CamxResultExt Isp Error Hw Stop";
                break;

            // Icp error reason types
            case CamxResultExtIcpErrorUnknown:
                rpResultString = "CamxResultExtIcpErrorUnknown";
                rpResultDescription = "Description: CamxResultExt Icp Error Unknown";
                break;
            case CamxResultExtIcpErrorFrameProcessFailure:
                rpResultString = "CamxResultExtIcpErrorFrameProcessFailure";
                rpResultDescription = "Description: CamxResultExt Icp Error Frame Process Failure";
                break;
            case CamxResultExtIcpErrorConfigErr:
                rpResultString = "CamxResultExtIcpErrorConfigErr";
                rpResultDescription = "Description: CamxResultExt Icp Error Config Err";
                break;

            // Jpeg error reason types
            case CamxResultExtJpegErrorUnknown:
                rpResultString = "CamxResultExtJpegErrorUnknown";
                rpResultDescription = "Description: CamxResultExt Jpeg Error Unknown";
                break;
            case CamxResultExtJpegErrorInvldCmd:
                rpResultString = "CamxResultExtJpegErrorInvldCmd";
                rpResultDescription = "Description: CamxResultExt Jpeg Error Invld Cmd";
                break;
            case CamxResultExtJpegErrorSetIrqCb:
                rpResultString = "CamxResultExtJpegErrorSetIrqCb";
                rpResultDescription = "Description: CamxResultExt Jpeg Error Set Irq Cb";
                break;
            case CamxResultExtJpegErrorHwResetFailed:
                rpResultString = "CamxResultExtJpegErrorHwResetFailed";
                rpResultDescription = "Description: CamxResultExt Jpeg Error Hw Reset Failed";
                break;
            case CamxResultExtJpegErrorCdmChangeBaseErr:
                rpResultString = "CamxResultExtJpegErrorCdmChangeBaseErr";
                rpResultDescription = "Description: CamxResultExt Jpeg Error Cdm Change Base Err";
                break;
            case CamxResultExtJpegErrorCdmConfigErr:
                rpResultString = "CamxResultExtJpegErrorCdmConfigErr";
                rpResultDescription = "Description: CamxResultExt Jpeg Error Cdm Config Err";
                break;
            case CamxResultExtJpegErrorStartHwErr:
                rpResultString = "CamxResultExtJpegErrorStartHwErr";
                rpResultDescription = "Description: CamxResultExt Jpeg Error Start Hw Err";
                break;

            // Fd error reason types
            case CamxResultExtFdErrorUnknown:
                rpResultString = "CamxResultExtFdErrorUnknown";
                rpResultDescription = "Description: CamxResultExt Fd Error Unknown";
                break;
            case CamxResultExtFdErrorIrqFrameDone:
                rpResultString = "CamxResultExtFdErrorIrqFrameDone";
                rpResultDescription = "Description: CamxResultExt Fd Error Irq Frame Done";
                break;
            case CamxResultExtFdErrorIrqResetDone:
                rpResultString = "CamxResultExtFdErrorIrqResetDone";
                rpResultDescription = "Description: CamxResultExt Fd Error Irq Reset Done";
                break;
            case CamxResultExtFdErrorHalt:
                rpResultString = "CamxResultExtFdErrorHalt";
                rpResultDescription = "Description: CamxResultExt Fd Error Halt";
                break;

            // Lrme error reason types
            case CamxResultExtLrmeErrorUnknown:
                rpResultString = "CamxResultExtLrmeErrorUnknown";
                rpResultDescription = "Description: CamxResultExt Lrme Error Unknown";
                break;
            case CamxResultExtLrmeErrorCbError:
                rpResultString = "CamxResultExtLrmeErrorCbError";
                rpResultDescription = "Description: CamxResultExt Lrme Error Cb Error";
                break;

            // Ope error reason types
            case CamxResultExtOpeErrorUnknown:
                rpResultString = "CamxResultExtOpeErrorUnknown";
                rpResultDescription = "Description: CamxResultExt Ope Error Unknown";
                break;
            case CamxResultExtOpeErrorPageFault:
                rpResultString = "CamxResultExtOpeErrorPageFault";
                rpResultDescription = "Description: CamxResultExt Ope Error Page Fault";
                break;
            case CamxResultExtOpeErrorHwHang:
                rpResultString = "CamxResultExtOpeErrorHwHang";
                rpResultDescription = "Description: CamxResultExt Ope Error Hw Hang";
                break;
            case CamxResultExtOpeErrorHalt:
                rpResultString = "CamxResultExtOpeErrorHalt";
                rpResultDescription = "Description: CamxResultExt Ope Error Halt";
                break;
            case CamxResultExtOpeErrorConfigErr:
                rpResultString = "CamxResultExtOpeErrorConfigErr";
                rpResultDescription = "Description: CamxResultExt Ope Error Config Err";
                break;
            case CamxResultExtOpeErrorHwFlush:
                rpResultString = "CamxResultExtOpeErrorHwFlush";
                rpResultDescription = "Description: CamxResultExt Ope Error Hw Flush";
                break;
            case CamxResultExtOpeErrorHwResubmit:
                rpResultString = "CamxResultExtOpeErrorHwResubmit";
                rpResultDescription = "Description: CamxResultExt Ope Error Hw Resubmit";
                break;
            case CamxResultExtOpeErrorHwResetDone:
                rpResultString = "CamxResultExtOpeErrorHwResetDone";
                rpResultDescription = "Description: CamxResultExt Ope Error Hw Reset Done";
                break;
            case CamxResultExtOpeErrorHwError:
                rpResultString = "CamxResultExtOpeErrorHwError";
                rpResultDescription = "Description: CamxResultExt Ope Error Hw Error";
                break;
            case CamxResultExtOpeErrorInvldCmd:
                rpResultString = "CamxResultExtOpeErrorInvldCmd";
                rpResultDescription = "Description: CamxResultExt Ope Error Invld Cmd";
                break;
            case CamxResultExtOpeErrorHwResetFailed:
                rpResultString = "CamxResultExtOpeErrorHwResetFailed";
                rpResultDescription = "Description: CamxResultExt Ope Error Hw Reset Failed";
                break;


            // Custom node extended error codes (Starts from 10240)
            case CamxResultExtCustomBase:
                rpResultString      = "CamxResultExtCustomBase";
                rpResultDescription = "Description: ";
                break;

            // CHI extended error codes (Starts from 20000)
            case CDKResultExceedThreshold:
                rpResultString      = "CDKResultExceedThreshold";
                rpResultDescription = "Description: FGM time out for Requests";
                break;

            case CDKResultUnProcessedRequest:
                rpResultString      = "CDKResultUnProcessedRequest";
                rpResultDescription = "Description: HAL requests has not been processed";
                break;

            case CDKResultFwkDump:
                rpResultString      = "CDKResultFwkDump";
                rpResultDescription = "Description: Framework requested Dump";
                break;

            case CDKResultETimeout:
                rpResultString      = "CDKResultETimeout";
                rpResultDescription = "Description: CDK Error Timeout";
                break;

            // Sensor Error Codes (Starts from 3072)
            case CamxResultExtSensorPDAFConfigurationFailed:
                rpResultString      = "CamxResultExtSensorPDAFConfigurationFailed";
                rpResultDescription = "Description: Sensor PDAF Configuration Failed";
                break;

            case CamxResultExtSensorDeviceCSLReleaseFailed:
                rpResultString      = "CamxResultExtSensorDeviceCSLReleaseFailed";
                rpResultDescription = "Description: Sensor Device CSLRelease Failed";
                break;

            default:
                rpResultString      = "CamxResultExtUnknownError";
                rpResultDescription = "Description: Unknown Error";
                return;
        }
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FindClosestInSortedIntArray
    ///
    /// @brief  Find the closest integer position index in the sorted integer array
    ///
    /// @param  pArray  pointer to sorted array in which the the search needs to be performed
    /// @param  size    Size of the array
    /// @param  value   Value to be searched
    ///
    /// @return UINT Position of the closest integer.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static UINT FindClosestInSortedIntArray(
        const INT16* pArray,
        UINT         size,
        INT          value)
    {
        UINT index       = 0;
        BOOL isAscending = (pArray[0] < pArray[size - 1]) ? TRUE : FALSE;

        if (TRUE == isAscending)
        {
            index = FindClosestInAscendingSortedIntArray(pArray, size, value);
        }
        else
        {
            index = FindClosestInDescendingSortedIntArray(pArray, size, value);
        }

        return index;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FenceErrorToString
    ///
    /// @brief  Converts a Fence Error code to a string represents the error
    ///
    /// @param  errorCode The Fence Error code to convert
    ///
    /// @return The error string represents the fence error
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CAMX_INLINE const CHAR* FenceErrorToString(
        UINT32 errorCode)
    {
        const CHAR* pResultString;

        switch (errorCode)
        {
            // Fence Error reason types
            case CamxResultExtCommonFenceUnused:
                pResultString = "CamxResultExtCommonFenceUnused";
                break;
            case CamxResultExtCommonFenceSuccess:
                pResultString = "CamxResultExtCommonFenceSuccess";
                break;
            case CamxResultExtCommonFenceFlush:
                pResultString = "CamxResultExtCommonFenceFlush";
                break;
            case CamxResultExtCommonFenceStop:
                pResultString = "CamxResultExtCommonFenceStop";
                break;
            case CamxResultExtCommonFenceSynx:
                pResultString = "CamxResultExtCommonFenceSynx";
                break;
            case CamxResultExtCommonFenceRegPayload:
                pResultString = "CamxResultExtCommonFenceRegPayload";
                break;
            case CamxResultExtCommonFenceSyncSignal:
                pResultString = "CamxResultExtCommonFenceSyncSignal";
                break;
            case CamxResultExtCommonFenceRelease:
                pResultString = "CamxResultExtCommonFenceRelease";
                break;

            // Isp Error reason types
            case CamxResultExtIspErrorUnknown:
                pResultString = "CamxResultExtIspErrorUnknown";
                break;
            case CamxResultExtIspErrorBubble:
                pResultString = "CamxResultExtIspErrorBubble";
                break;
            case CamxResultExtIspErrorOverflow:
                pResultString = "CamxResultExtIspErrorOverflow";
                break;
            case CamxResultExtIspErrorP2iError:
                pResultString = "CamxResultExtIspErrorP2iError";
                break;
            case CamxResultExtIspErrorViolation:
                pResultString = "CamxResultExtIspErrorViolation";
                break;
            case CamxResultExtIspErrorBusifOverflow:
                pResultString = "CamxResultExtIspErrorBusifOverflow";
                break;
            case CamxResultExtIspErrorFlush:
                pResultString = "CamxResultExtIspErrorFlush";
                break;
            case CamxResultExtIspErrorHwStop:
                pResultString = "CamxResultExtIspErrorHwStop";
                break;

            // Icp Error reason types
            case CamxResultExtIcpErrorUnknown:
                pResultString = "CamxResultExtIcpErrorUnknown";
                break;
            case CamxResultExtIcpErrorFrameProcessFailure:
                pResultString = "CamxResultExtIcpErrorFrameProcessFailure";
                break;
            case CamxResultExtIcpErrorConfigErr:
                pResultString = "CamxResultExtIcpErrorConfigErr";
                break;

            // Jpeg Error reason types
            case CamxResultExtJpegErrorUnknown:
                pResultString = "CamxResultExtJpegErrorUnknown";
                break;
            case CamxResultExtJpegErrorInvldCmd:
                pResultString = "CamxResultExtJpegErrorInvldCmd";
                break;
            case CamxResultExtJpegErrorSetIrqCb:
                pResultString = "CamxResultExtJpegErrorSetIrqCb";
                break;
            case CamxResultExtJpegErrorHwResetFailed:
                pResultString = "CamxResultExtJpegErrorHwResetFailed";
                break;
            case CamxResultExtJpegErrorCdmChangeBaseErr:
                pResultString = "CamxResultExtJpegErrorCdmChangeBaseErr";
                break;
            case CamxResultExtJpegErrorCdmConfigErr:
                pResultString = "CamxResultExtJpegErrorCdmConfigErr";
                break;
            case CamxResultExtJpegErrorStartHwErr:
                pResultString = "CamxResultExtJpegErrorStartHwErr";
                break;

            // Fd Error reason types
            case CamxResultExtFdErrorUnknown:
                pResultString = "CamxResultExtFdErrorUnknown";
                break;
            case CamxResultExtFdErrorIrqFrameDone:
                pResultString = "CamxResultExtFdErrorIrqFrameDone";
                break;
            case CamxResultExtFdErrorIrqResetDone:
                pResultString = "CamxResultExtFdErrorIrqResetDone";
                break;
            case CamxResultExtFdErrorHalt:
                pResultString = "CamxResultExtFdErrorHalt";
                break;

            // Lrme Error reason types
            case CamxResultExtLrmeErrorUnknown:
                pResultString = "CamxResultExtLrmeErrorUnknown";
                break;
            case CamxResultExtLrmeErrorCbError:
                pResultString = "CamxResultExtLrmeErrorCbError";
                break;

            // Ope Error reason types
            case CamxResultExtOpeErrorUnknown:
                pResultString = "CamxResultExtOpeErrorUnknown";
                break;
            case CamxResultExtOpeErrorPageFault:
                pResultString = "CamxResultExtOpeErrorPageFault";
                break;
            case CamxResultExtOpeErrorHwHang:
                pResultString = "CamxResultExtOpeErrorHwHang";
                break;
            case CamxResultExtOpeErrorHalt:
                pResultString = "CamxResultExtOpeErrorHalt";
                break;
            case CamxResultExtOpeErrorConfigErr:
                pResultString = "CamxResultExtOpeErrorConfigErr";
                break;
            case CamxResultExtOpeErrorHwFlush:
                pResultString = "CamxResultExtOpeErrorHwFlush";
                break;
            case CamxResultExtOpeErrorHwResubmit:
                pResultString = "CamxResultExtOpeErrorHwResubmit";
                break;
            case CamxResultExtOpeErrorHwResetDone:
                pResultString = "CamxResultExtOpeErrorHwResetDone";
                break;
            case CamxResultExtOpeErrorHwError:
                pResultString = "CamxResultExtOpeErrorHwError";
                break;
            case CamxResultExtOpeErrorInvldCmd:
                pResultString = "CamxResultExtOpeErrorInvldCmd";
                break;
            case CamxResultExtOpeErrorHwResetFailed:
                pResultString = "CamxResultExtOpeErrorHwResetFailed";
                break;

            default:
                pResultString = "NoErrorReason";
                break;
        }

        return pResultString;
    }

private:
    Utils(const Utils&) = delete;               ///< Disallow the copy constructor
    Utils& operator=(const Utils&) = delete;    ///< Disallow assignment operator
    Utils() = delete;                           ///< Disallow constructor, this class contains only static functions
    ~Utils() = delete;                          ///< Disallow destructor, this class contains only static functions
};

CAMX_NAMESPACE_END

#endif // CAMXUTILS_H
