/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// using System.Collections.Generic; using System.Linq; namespace wasSharp { public static class BitTwiddling { /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Swaps two integers passed by reference using XOR. /// /// first integer to swap /// second integer to swap public static void XORSwap(ref int q, ref int p) { q ^= p; p ^= q; q ^= p; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Checks whether a flag is set for a bitmask. /// /// a data type /// a data type /// the mask to check the flag for /// the flag to check /// true in case the flag is set public static bool IsMaskFlagSet(this T mask, U flag) where T : struct where U : struct { return unchecked(mask as dynamic & flag as dynamic) != 0; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Sets a flag for a bitmask. /// /// a data type /// a data type /// the mask to set the flag on /// the flag to set public static void SetMaskFlag(ref T mask, U flag) where T : struct where U : struct { mask = unchecked(mask as dynamic | flag as dynamic); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Create a bitmask from multiple flags. /// /// a data type /// the flags to set /// a bitmask public static T CreateMask(this IEnumerable flag) where T : struct { return flag.Aggregate((o, p) => unchecked(o as dynamic | p as dynamic)); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Unset a flag for a bitmask. /// /// a data type /// a data type /// the mask to unset the flag on /// the flag to unset public static void UnsetMaskFlag(ref T mask, U flag) { mask = unchecked(mask as dynamic & ~(flag as dynamic)); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Toggle a flag for a bitmask. /// /// a data type /// a data type /// the mask to toggle the flag on /// the flag to toggle public static void ToggleMaskFlag(ref T mask, U flag) { mask = unchecked(mask as dynamic ^ flag as dynamic); } /// /// Computes the previous power of two. /// /// the integer /// the previous power of two /// Adapted from Hacker's Delight ISBN-10:0201914654 public static T PreviousPowerOfTwo(this T x) { var y = x as dynamic; unchecked { y = y | (y >> 1); y = y | (y >> 2); y = y | (y >> 4); y = y | (y >> 8); y = y | (y >> 16); return y - (y >> 1); } } /// /// Determines if a number is a power of two. /// /// the number type /// the number /// true of the number is a power of two public static bool IsPowerOfTwo(this T x) { var y = x as dynamic; return (y != 0) && ((y & (y - 1)) == 0); } } }