Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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;
- }
- fn digits10(comptime N: type, n: N, comptime unroll: ?u8) usize {
- if (comptime is_signed(N)) {
- const nbits = comptime bitcount(N);
- const unsigned_friend = @IntType(false, nbits);
- if (is_negative(N, n)) {
- return digits10(unsigned_friend, @intCast(unsigned_friend, n * -1), 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) : ({overflowed = @mulWithOverflow(usize, check, 10, &check); digits += 1;}) {
- if (n < check) {
- return digits;
- }
- }
- return digits;
- }
- }
- test "testimpl" {
- var n: usize = digits10(isize, -12345, null);
- std.debug.warn("{}\n", n);
- std.debug.assert(n == 5);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement