Created
August 17, 2024 00:41
-
-
Save voronoipotato/fa4834afa20f3b00d55b64e378080489 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| open BenchmarkDotNet.Attributes | |
| open BenchmarkDotNet.Running | |
| open BenchmarkDotNet.Jobs | |
| open System | |
| open Microsoft.FSharp.NativeInterop | |
| type Chars () = | |
| static member chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".AsSpan() | |
| let chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
| let b36Unfold (number: int) = | |
| let unfoldFunc n = | |
| if n = 0 then None | |
| else | |
| let remainder = n % 36 | |
| let quotient = n / 36 | |
| Some (chars.[remainder], quotient) | |
| Array.unfold unfoldFunc number | |
| |> Array.rev | |
| |> System.String | |
| let b36Span (number:int) = | |
| let digits = Math.Log(number, 36.0) |> ceil |> int | |
| let mem = NativePtr.stackalloc<char>(digits) |> NativePtr.toVoidPtr | |
| let nativeSpan = Span<char>(mem, digits) | |
| let mutable (n:int) = number | |
| for identifier = digits downto 1 do //identifier = 1 to digits do | |
| nativeSpan[identifier-1] <- Chars.chars.[n%36] | |
| n <- n/36 | |
| nativeSpan.ToString() | |
| let toBase36 n = | |
| let mutable num = n | |
| let mutable r = 0 | |
| let mutable newNumber = "" | |
| while num >= 36 do | |
| r <- num % 36 | |
| newNumber <- string (chars.[r]) + newNumber | |
| num <- num / 36 | |
| newNumber <- string (chars.[num]) + newNumber | |
| newNumber | |
| let toBase36Rec n = | |
| let rec toBase36 n state = | |
| if n < 36 then | |
| string state | |
| else | |
| let r = n % 36 | |
| let newState = chars[r] :: state | |
| toBase36 (n/36) newState | |
| toBase36 n List.empty | |
| [<SimpleJob(RuntimeMoniker.Net80)>] | |
| type Benchmarks() = | |
| [<Params(123, 245685, 3000000)>] | |
| member val size = 0 with get, set | |
| [<Benchmark>] | |
| member __.B36Unfold () = b36Unfold __.size | |
| [<Benchmark>] | |
| member __.B36Span () = b36Span __.size | |
| [<Benchmark>] | |
| member __.B36Mutable () = toBase36 __.size | |
| [<Benchmark>] | |
| member __.B36Rec () = toBase36Rec __.size | |
| BenchmarkRunner.Run<Benchmarks>() |> ignore |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I would just make the function take an unsigned int personally. negative base36 is not valid for most consumers