Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C++ (Circle)
CIRCT
Clean
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
GLSL
Go
Haskell
HLSL
Hook
Hylo
IL
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Nim
Objective-C
Objective-C++
OCaml
OpenCL C
Pascal
Pony
Python
Racket
Ruby
Rust
Snowball
Scala
Solidity
Spice
SPIR-V
Swift
LLVM TableGen
Toit
TypeScript Native
V
Vala
Visual Basic
WASM
Zig
Javascript
GIMPLE
Ygen
zig source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
zig 0.10.0
zig 0.11.0
zig 0.12.0
zig 0.12.1
zig 0.13.0
zig 0.2.0
zig 0.3.0
zig 0.4.0
zig 0.5.0
zig 0.6.0
zig 0.7.0
zig 0.7.1
zig 0.8.0
zig 0.9.0
zig trunk
Options
Source code
const std = @import("std"); const TypeId = @import("builtin").TypeId; fn is_signed(comptime N: type) bool { switch (@typeInfo(N)) { TypeId.Int => |int| { return int.is_signed; }, else => { @compileError("Is_signed is only available on integer types. Found `" ++ @typeName(N) ++ "`."); } } } fn bitcount(comptime N: type) u32 { switch (@typeInfo(N)) { TypeId.Int => |int| { return @intCast(u32, int.bits); }, else => { @compileError("Bitcount only available on integer types. Found `" ++ @typeName(N) ++ "`."); } } } fn is_negative(comptime N: type, num: N) bool { return num < 0; } pub const FULLY_UNROLL: ?u8 = null; /// Returns the number of digits in base 10 that `n` consists of. /// Also takes an optional `unroll` parameter, when null is passed, /// this function is fully unrolled, becomes a simple lookup, /// otherwise, this function will unroll it's inner loop for `unroll` times. pub fn digits10(comptime N: type, n: N, comptime unroll: ?u8) usize { // If we encouter a signed int, // check if it's negative, // if so, multiply by minus one (make positive), and call digits10 on the unsigned version of the int, // if not negative, just call digits10 on the unsigned version, // and if we dont encouter a signed int, just skip this whole if :) if (comptime is_signed(N)) { const nbits = comptime bitcount(N); const unsigned_friend = @IntType(false, nbits); if (is_negative(N, n)) { // we can't use @intCast for some reason :( var num = @bitCast(unsigned_friend, n *% -1); return digits10(unsigned_friend, num, unroll); } else { return digits10(unsigned_friend, @intCast(unsigned_friend, n), unroll); } } comptime var digits: usize = 1; comptime var check: usize = 10; if (comptime unroll) |unroll_count| { var num: usize = n; var result: usize = 0; comptime var counter: usize = 0; while (true) { inline while (counter != unroll_count) : ({counter += 1; check *= 10; digits += 1;}) { if (num < check) { return result + digits; } } result += unroll_count; num /= comptime (check / 10); } } else { comptime var overflowed = false; inline while (check <= @maxValue(N) and !overflowed) : ({ digits += 1; overflowed = @mulWithOverflow(usize, check, 10, &check);}) { if (n < check) { return digits; } } return digits; } } export fn digits10usize(n: usize) usize { return digits10(usize, n, FULLY_UNROLL); } fn iter(comptime N: usize) [N]void { return undefined; } fn assert_value(length: usize, comptime inttype: type, input: inttype, comptime unroll_count: ?u8) void { std.debug.assert(length == digits10(inttype, input, unroll_count)); } test "corner cases" { const bitcounts = []u32 {8, 16, 32, 64}; const lenghts = []usize {3, 5, 10, 19}; inline for(bitcounts) |nbits, idx| { comptime var unsigned_type = @IntType(false, @intCast(u32, nbits)); comptime var signed_type = @IntType(true, @intCast(u32, nbits)); const length = lenghts[idx]; inline for (comptime iter(10)) |_, i| { const unroll_count = @intCast(u8, i + 1); assert_value(length, signed_type, @minValue(signed_type), unroll_count); assert_value(length, signed_type, @maxValue(signed_type), unroll_count); assert_value(1, unsigned_type, 0, unroll_count); // i64 has a length of 19, but u64 20.. :3 if (unsigned_type == u64) { assert_value(length + 1, unsigned_type, @maxValue(unsigned_type), unroll_count); } else { assert_value(length, unsigned_type, @maxValue(unsigned_type), unroll_count); } } assert_value(1, unsigned_type, 0, FULLY_UNROLL); if (unsigned_type == u64) { assert_value(length + 1, unsigned_type, @maxValue(unsigned_type), FULLY_UNROLL); } else { assert_value(length, unsigned_type, @maxValue(unsigned_type), FULLY_UNROLL); } } }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
About the author
Statistics
Changelog
Version tree