Even or Odd 2

In a previous post I have looked into different implementations for deciding if an integer is odd or an even number.

At the time of writing this post, the latest .NET 7 Preview 5 offers a new API to answer the above question. There are two new static abstract methods defined on INumberBase type which is implemented by numerous types including Int32. One can use these methods as static methods on generic type parameters restricted by INumberBase interface or as static methods on implementing types.

For example using it with ints:

public bool StatAbsIsOddOrEven(int number) => int.IsOddInteger(number);

Each type implementing INumberBase may have its own concrete implementation. Int32 implements the IsOddInteger() method by bitwise ANDing the input with 1 and comparing the results to 0.

As I had a few implementations presented in a previous post, I have been eager to find out how this method performs against those. Running the same benchmarks including the new method yields the following results:

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
Intel Core i5-1035G4 CPU 1.10GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=7.0.100-preview.5.22307.18
  [Host]     : .NET 7.0.0 (7.0.22.30112), X64 RyuJIT
  DefaultJob : .NET 7.0.0 (7.0.22.30112), X64 RyuJIT


|             Method |     Mean |    Error |   StdDev |   Median |
|------------------- |---------:|---------:|---------:|---------:|
|         RightShift | 63.03 us | 0.931 us | 0.727 us | 62.92 us |
|           UnsafeAs | 40.39 us | 0.792 us | 1.366 us | 41.03 us |
| StatAbsIsOddOrEven | 49.47 us | 0.979 us | 1.341 us | 49.97 us |

This implementation performs reasonably well on a large random set of integers, although the current runtime implementation involves having branching operation with the comparison.

Looking at how the JIT compiles such a static method into assembly:

00007ffb`73381330 55              push    rbp
00007ffb`73381331 488bec          mov     rbp,rsp
00007ffb`73381334 894d10          mov     dword ptr [rbp+10h],ecx
00007ffb`73381337 8b4510          mov     eax,dword ptr [rbp+10h]
00007ffb`7338133a 83e001          and     eax,1
00007ffb`7338133d 85c0            test    eax,eax
00007ffb`7338133f 0f94c0          sete    al
00007ffb`73381342 0fb6c0          movzx   eax,al
00007ffb`73381345 5d              pop     rbp
00007ffb`73381346 c3              ret

I have used WinDBG and the !name2ee command to retrieve the JITted code.

Other than the prolog and epilog the method compares the input with 1 and then uses the result to decide if the input is odd or even.