Livt packages

Eccelerators.BitTwiddling

Version 0.1.1

Readable 32-bit bit manipulation, counting, scanning, permutation, and arithmetic utilities for Livt.

Published files (26)

src/integer/IntegerProperties.lvt

namespace Eccelerators.BitTwiddling.Integer

/**
 * Provides common properties and transformations for fixed-width 32-bit
 * integers.
 *
 * Functions use int only where signed interpretation is part of the contract;
 * raw bit patterns and non-negative magnitudes use uint.
 */
class IntegerProperties
{
    /**
     * Returns a mask representing the sign of value.
     *
     * Non-negative values return 0. Negative values return -1, whose 32-bit
     * two's-complement representation has every bit set.
     */
    public static fn SignMask[](value: int) int
    {
        return value >> 31
    }

    /**
     * Returns true when x and y have different signs.
     *
     * Zero is non-negative, so zero and a negative value have opposite signs.
     */
    public static fn HaveOppositeSigns[](x: int, y: int) bool
    {
        return (x ^ y) < 0
    }

    /**
     * Returns the unsigned magnitude of value.
     *
     * Returning uint allows the magnitude of -2147483648 to be represented as
     * 0x80000000 instead of overflowing a signed int.
     */
    public static fn AbsoluteValueBits[](value: int) uint
    {
        var mask: int = value >> 31
        return ((value + mask) ^ mask) as uint
    }

    /**
     * Returns the smaller of signed values x and y.
     */
    public static fn Minimum[](x: int, y: int) int
    {
        if (x < y)
        {
            return x
        }

        return y
    }

    /**
     * Returns the larger of signed values x and y.
     */
    public static fn Maximum[](x: int, y: int) int
    {
        if (x > y)
        {
            return x
        }

        return y
    }

    /**
     * Returns true when value is an exact positive power of two.
     *
     * Zero returns false. Every valid power of two has exactly one set bit.
     */
    public static fn IsPowerOfTwo[](value: uint) bool
    {
        return (value != (0 as uint)) &&
            ((value & (value - (1 as uint))) == (0 as uint))
    }

    /**
     * Returns the smallest power of two greater than or equal to value.
     *
     * Zero returns 1. Values above 0x80000000 return 0 because the mathematical
     * result cannot be represented by uint. Existing powers of two are returned
     * unchanged.
     */
    public static fn RoundUpToPowerOfTwo[](value: uint) uint
    {
        if (value == (0 as uint))
        {
            return 1
        }

        if (value > (0x80000000 as uint))
        {
            return 0
        }

        var workingValue: uint = value - (1 as uint)
        workingValue = workingValue | (workingValue >> 1)
        workingValue = workingValue | (workingValue >> 2)
        workingValue = workingValue | (workingValue >> 4)
        workingValue = workingValue | (workingValue >> 8)
        workingValue = workingValue | (workingValue >> 16)
        return workingValue + (1 as uint)
    }

    /**
     * Interprets the low bitWidth bits of value as a signed two's-complement
     * number and sign-extends it to int.
     *
     * Valid widths are 1 through 32. Bits above bitWidth are ignored. Invalid
     * widths return 0.
     */
    public static fn SignExtend[](value: uint, bitWidth: int) int
    {
        if ((bitWidth < 1) || (bitWidth > 32))
        {
            return 0
        }

        if (bitWidth == 32)
        {
            return value as int
        }

        var signBit: uint = (1 as uint) << (bitWidth - 1)
        var widthMask: uint = ((1 as uint) << bitWidth) - (1 as uint)
        var maskedValue: uint = value & widthMask
        return ((maskedValue ^ signBit) - signBit) as int
    }
}