Even or Odd 2
09/25/2022
3 minutes
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 int
s:
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.