Even or Odd 2
09/25/2022 | 3 minutes to read
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
!name2eecommand 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.