Skip to content

Instantly share code, notes, and snippets.

@AnthonyMastrean
Created September 9, 2013 20:52
Show Gist options
  • Save AnthonyMastrean/6501338 to your computer and use it in GitHub Desktop.
Save AnthonyMastrean/6501338 to your computer and use it in GitHub Desktop.
A comparison of unit mask converters
[Behaviors]
public class UnitMaskConverterBehaviors
{
It should_convert_0_to_A = () => _converter.Convert(0).ShouldEqual('A');
It should_convert_1_to_B = () => _converter.Convert(1).ShouldEqual('B');
It should_convert_2_to_C = () => _converter.Convert(2).ShouldEqual('C');
It should_convert_4_to_D = () => _converter.Convert(4).ShouldEqual('D');
It should_convert_8_to_E = () => _converter.Convert(8).ShouldEqual('E');
It should_convert_16_to_F = () => _converter.Convert(16).ShouldEqual('F');
It should_convert_32_to_G = () => _converter.Convert(32).ShouldEqual('G');
It should_convert_64_to_H = () => _converter.Convert(64).ShouldEqual('H');
It should_convert_128_to_I = () => _converter.Convert(128).ShouldEqual('I');
It should_convert_256_to_J = () => _converter.Convert(256).ShouldEqual('J');
It should_convert_512_to_K = () => _converter.Convert(512).ShouldEqual('K');
It should_convert_1024_to_L = () => _converter.Convert(1024).ShouldEqual('L');
It should_convert_2048_to_M = () => _converter.Convert(2048).ShouldEqual('M');
It should_convert_4096_to_N = () => _converter.Convert(4096).ShouldEqual('N');
It should_convert_8192_to_O = () => _converter.Convert(8192).ShouldEqual('O');
It should_convert_16384_to_P = () => _converter.Convert(16384).ShouldEqual('P');
It should_convert_32768_to_Q = () => _converter.Convert(32768).ShouldEqual('Q');
It should_convert_65536_to_R = () => _converter.Convert(65536).ShouldEqual('R');
It should_convert_131072_to_S = () => _converter.Convert(131072).ShouldEqual('S');
It should_convert_262144_to_T = () => _converter.Convert(262144).ShouldEqual('T');
It should_convert_524288_to_U = () => _converter.Convert(524288).ShouldEqual('U');
It should_convert_1048576_to_V = () => _converter.Convert(1048576).ShouldEqual('V');
It should_convert_2097152_to_W = () => _converter.Convert(2097152).ShouldEqual('W');
It should_convert_4194304_to_X = () => _converter.Convert(4194304).ShouldEqual('X');
It should_convert_8388608_to_Y = () => _converter.Convert(8388608).ShouldEqual('Y');
It should_convert_16777216_to_Z = () => _converter.Convert(16777216).ShouldEqual('Z');
protected static IUnitMaskConverter _converter;
}
[Behaviors]
public class UnitMaskPerformanceBehaviors
{
It should_take_less_than_one_millisecond_per_iteration = () =>
{
const double n = 10000000.0;
var stopwatch = Stopwatch.StartNew();
for (var count = 0; count <= n; count++)
{
var result = _converter.Convert(16777216);
}
stopwatch.Stop();
var iteration = stopwatch.ElapsedMilliseconds / n;
// Prints a message like this
// [WhateverUnitMaskConverter]: 10000000 iterations in 498 ms (0.000049800 ms/iteration)
Debug.Print("[{0}]: {1} iterations in {2} ms ({3:F9} ms/iteration)", _converter.GetType().Name, n, stopwatch.ElapsedMilliseconds, iteration);
iteration.ShouldBeLessThan(1);
};
protected static IUnitMaskConverter _converter;
}
public class BinaryUnitMaskConverter : IUnitMaskConverter
{
public char Convert(uint mask)
{
var result = System.Convert.ToString(mask, 2);
return result.Contains("1")
? (char)(result.Substring(result.IndexOf('1')).Length + 65)
: 'A';
}
}
public class LogUnitMaskConverter : IUnitMaskConverter
{
public char Convert(uint mask)
{
var result = Math.Log(mask, 2.0);
return result != double.NegativeInfinity
? (char)(result + 66)
: 'A';
}
}
public class LookupUnitMaskConverter : IUnitMaskConverter
{
private static readonly Dictionary<uint, char> map = new Dictionary<uint, char>
{
{ 0 , 'A' },
{ 1 , 'B' },
{ 2 , 'C' },
{ 4 , 'D' },
{ 8 , 'E' },
{ 16 , 'F' },
{ 32 , 'G' },
{ 64 , 'H' },
{ 128 , 'I' },
{ 256 , 'J' },
{ 512 , 'K' },
{ 1024 , 'L' },
{ 2048 , 'M' },
{ 4096 , 'N' },
{ 8192 , 'O' },
{ 16384 , 'P' },
{ 32768 , 'Q' },
{ 65536 , 'R' },
{ 131072 , 'S' },
{ 262144 , 'T' },
{ 524288 , 'U' },
{ 1048576 , 'V' },
{ 2097152 , 'W' },
{ 4194304 , 'X' },
{ 8388608 , 'Y' },
{ 16777216, 'Z' },
};
public char Convert(uint mask)
{
return map[mask];
}
}
public class OriginalUnitMaskConverter : IUnitMaskConverter
{
private static readonly char[] Units = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
public char Convert(uint mask)
{
var index = 0;
var array = new BitArray(BitConverter.GetBytes(mask));
foreach (bool var in array)
{
if (var)
break;
index++;
}
return Units[index];
}
}
public interface IUnitMaskConverter
{
char Convert(uint mask);
}
[Subject(typeof(IUnitMaskConverter))]
public class When_converting_unit_masks_by_original_method
{
Behaves_like<UnitMaskConverterBehaviors> a_unit_mask_converter;
Behaves_like<UnitMaskPerformanceBehaviors> a_high_performance_converter;
protected static OriginalUnitMaskConverter _converter = new OriginalUnitMaskConverter();
}
[Subject(typeof(IUnitMaskConverter))]
public class When_converting_unit_masks_by_lookup
{
Behaves_like<UnitMaskConverterBehaviors> a_unit_mask_converter;
Behaves_like<UnitMaskPerformanceBehaviors> a_high_performance_converter;
protected static LookupUnitMaskConverter _converter = new LookupUnitMaskConverter();
}
[Subject(typeof(IUnitMaskConverter))]
public class When_converting_unit_masks_by_log
{
Behaves_like<UnitMaskConverterBehaviors> a_unit_mask_converter;
Behaves_like<UnitMaskPerformanceBehaviors> a_high_performance_converter;
protected static LogUnitMaskConverter _converter = new LogUnitMaskConverter();
}
[Subject(typeof(IUnitMaskConverter))]
public class When_converting_unit_masks_by_binary
{
Behaves_like<UnitMaskConverterBehaviors> a_unit_mask_converter;
Behaves_like<UnitMaskPerformanceBehaviors> a_high_performance_converter;
protected static BinaryUnitMaskConverter _converter = new BinaryUnitMaskConverter();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment