Advertisement
Guest User

Untitled

a guest
Feb 18th, 2019
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.19 KB | None | 0 0
  1. const std = @import("std");
  2. const TypeId = @import("builtin").TypeId;
  3.  
  4. fn is_signed(comptime N: type) bool {
  5.     switch (@typeInfo(N)) {
  6.         TypeId.Int => |int| {
  7.             return int.is_signed;
  8.         },
  9.         else => {
  10.             @compileError("Is_signed is only available on integer types. Found `" ++ @typeName(N) ++ "`.");
  11.         }
  12.     }
  13. }
  14.  
  15. fn bitcount(comptime N: type) u32 {
  16.     switch (@typeInfo(N)) {
  17.         TypeId.Int => |int| {
  18.             return @intCast(u32, int.bits);
  19.         },
  20.         else => {
  21.             @compileError("Bitcount only available on integer types. Found `" ++ @typeName(N) ++ "`.");
  22.         }
  23.     }
  24. }
  25.  
  26. fn is_negative(comptime N: type, num: N) bool {
  27.     return num < 0;
  28. }
  29.  
  30. fn digits10(comptime N: type, n: N, comptime unroll: ?u8) usize {
  31.     if (comptime is_signed(N)) {
  32.  
  33.         const nbits = comptime bitcount(N);
  34.  
  35.         const unsigned_friend = @IntType(false, nbits);
  36.  
  37.         if (is_negative(N, n)) {
  38.             return digits10(unsigned_friend, @intCast(unsigned_friend, n * -1), unroll);
  39.         }
  40.         else {
  41.             return digits10(unsigned_friend, @intCast(unsigned_friend, n), unroll);
  42.         }
  43.     }
  44.  
  45.     comptime var digits: usize = 1;
  46.     comptime var check: usize = 10;
  47.  
  48.     if (comptime unroll) |unroll_count| {
  49.         var num: usize = n;
  50.         var result: usize = 0;
  51.         comptime var counter: usize = 0;
  52.  
  53.         while (true) {
  54.             inline while (counter != unroll_count) : ({counter += 1; check *= 10; digits += 1;}) {
  55.                 if (num < check) {
  56.                     return result + digits;
  57.                 }
  58.             }
  59.            
  60.             result += unroll_count;
  61.             num /= comptime (check / 10);
  62.         }
  63.     } else {
  64.         comptime var overflowed = false;
  65.         inline while (check <= @maxValue(N) and !overflowed) : ({overflowed = @mulWithOverflow(usize, check, 10, &check); digits += 1;}) {
  66.             if (n < check) {
  67.                 return digits;
  68.             }
  69.         }
  70.  
  71.         return digits;
  72.     }
  73. }
  74.  
  75. test "testimpl" {
  76.  
  77.     var n: usize = digits10(isize, -12345, null);
  78.     std.debug.warn("{}\n", n);
  79.     std.debug.assert(n == 5);
  80. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement