# Int is the base type of all integer types. # # There are five signed integer types: `Int8`, `Int16`, `Int32`, `Int64` and # `Int128`, being able to represent numbers of 8, 16, 32, 64, and 128 bits respectively. # There are five unsigned integer types: `UInt8`, `UInt16`, `UInt32`, `UInt64` # and `UInt128. # # An integer literal is an optional `+` or `-` sign, followed by # a sequence of digits and underscores, optionally followed by a suffix. # If no suffix is present, the literal's type is `Int32`, or `Int64` if the # number doesn't fit into an `Int32`: # # ``` # 1 # Int32 # # 1_i8 # Int8 # 1_i16 # Int16 # 1_i32 # Int32 # 1_i64 # Int64 # 1_i128 # Int128 # # 1_u8 # UInt8 # 1_u16 # UInt16 # 1_u32 # UInt32 # 1_u64 # UInt64 # 1_u128 # UInt128 # # +10 # Int32 # -20 # Int32 # # 2147483648 # Int64 # ``` # # Literals without a suffix that are larger than `Int64::MAX` represent a # `UInt64` if the number fits, e.g. `9223372036854775808` and # `0x80000000_00000000`. This behavior is deprecated and will become an error in # the future. # # The underscore `_` before the suffix is optional. # # Underscores can be used to make some numbers more readable: # # ``` # 1_000_000 # better than 1000000 # ``` # # Binary numbers start with `0b`: # # ``` # 0b1101 # == 13 # ``` # # Octal numbers start with `0o`: # # ``` # 0o123 # == 83 # ``` # # Hexadecimal numbers start with `0x`: # # ``` # 0xFE012D # == 16646445 # 0xfe012d # == 16646445 # ``` # # See [`Integer` literals](https://crystal-lang.org/reference/syntax_and_semantics/literals/integers.html) in the language reference. struct Int alias Signed = Int8 | Int16 | Int32 | Int64 | Int128 alias Unsigned = UInt8 | UInt16 | UInt32 | UInt64 | UInt128 alias Primitive = Signed | Unsigned # Returns a `Char` that has the unicode codepoint of `self`. # # Raises `ArgumentError` if this integer's value doesn't fit a char's range # (`0..0xd7ff` and `0xe000..0x10ffff`). # # ``` # 97.chr # => 'a' # ``` def chr : Char unless 0 <= self <= 0xd7ff || 0xe000 <= self <= Char::MAX_CODEPOINT raise ArgumentError.new("0x#{self.to_s(16)} out of char range") end unsafe_chr end def ~ self ^ -1 end # Divides `self` by *other* using floored division. # # In floored division, given two integers x and y: # * q = x / y is rounded toward negative infinity # * r = x % y has the sign of the second argument # * x == q*y + r # # For example: # # ```text # x y x / y x % y # 5 3 1 2 # -5 3 -2 1 # 5 -3 -2 -1 # -5 -3 1 -2 # ``` # # Raises if *other* is zero, or if *other* is -1 and # `self` is signed and is the minimum value for that # integer type. def //(other : Int::Primitive) check_div_argument other div = unsafe_div other mod = unsafe_mod other div -= 1 if other > 0 ? mod < 0 : mod > 0 div end # Divides `self` by *other* using truncated division. # # In truncated division, given two integers x and y: # * `q = x.tdiv(y)` is rounded toward zero # * `r = x.remainder(y)` has the sign of x # * `x == q*y + r` # # For example: # # ```text # x y x / y x % y # 5 3 1 2 # -5 3 -1 -2 # 5 -3 -1 2 # -5 -3 1 -2 # ``` # # Raises if *other* is `0`, or if *other* is `-1` and # `self` is signed and is the minimum value for that # integer type. def tdiv(other : Int) check_div_argument other unsafe_div other end private def check_div_argument(other) if other == 0 raise DivisionByZeroError.new end {% begin %} if self < 0 && self == {{@type}}::MIN && other == -1 raise ArgumentError.new "Overflow: {{@type}}::MIN / -1" end {% end %} end # Returns a `Tuple` of two elements containing the quotient # and modulus obtained by dividing `self` by *number* using # truncated division. # # ``` # 11.tdivmod(3) # => {3, 2} # 11.tdivmod(-3) # => {-4, -1} # ``` # # In truncated division, given two integers x and y: # * `q = x.tdiv(y)` is rounded toward zero # * `r = x.remainder(y)` has the sign of x # * `x == q*y + r` # # For example: # # ```text # x y x / y x % y # 5 3 1 2 # -5 3 -1 -2 # 5 -3 -1 2 # -5 -3 1 -2 # ``` # # Raises if *other* is `0`, or if *other* is `-1` and # `self` is signed and is the minimum value for that # integer type. def tdivmod(other : Int) check_div_argument other {unsafe_div(other), unsafe_mod(other)} end def fdiv(other) : Float64 to_f / other end # Returns `self` modulo *other*. # # This uses floored division. # # See `Int#/` for more details. def %(other : Int) {% begin %} if other == 0 raise DivisionByZeroError.new elsif self < 0 && self == {{@type}}::MIN && other == -1 self.class.new(0) elsif (self < 0) == (other < 0) self.unsafe_mod(other) else me = self.unsafe_mod(other) me == 0 ? me : me + other end {% end %} end # Returns `self` remainder *other*. # # This uses truncated division. # # See `Int#tdiv` for more details. def remainder(other : Int) {% begin %} if other == 0 raise DivisionByZeroError.new elsif self < 0 && self == {{@type}}::MIN && other == -1 self.class.new(0) else unsafe_mod other end {% end %} end # :nodoc: # # Computes (x * y) % z, but without intermediate overflows. # Precondition: `0 <= x < z && y >= 0` def self.mulmod(x, y, z) result = zero while y > 0 if y.bits_set?(1) # result = (result + x) % z if result >= z &- x result &-= z &- x else result &+= x end end # x = (x + x) % z if x >= z &- x x &-= z &- x else x = x.unsafe_shl(1) end y = y.unsafe_shr(1) end result end # Returns the result of shifting this number's bits *count* positions to the right. # Also known as arithmetic right shift. # # * If *count* is greater than the number of bits of this integer, returns 0 # * If *count* is negative, a left shift is performed # # ``` # 8000 >> 1 # => 4000 # 8000 >> 2 # => 2000 # 8000 >> 32 # => 0 # 8000 >> -1 # => 16000 # # -8000 >> 1 # => -4000 # ``` def >>(count : Int) if count < 0 self << count.abs elsif count < sizeof(self) * 8 self.unsafe_shr(count) else self.class.zero end end # Returns the result of shifting this number's bits *count* positions to the left. # # * If *count* is greater than the number of bits of this integer, returns 0 # * If *count* is negative, a right shift is performed # # ``` # 8000 << 1 # => 16000 # 8000 << 2 # => 32000 # 8000 << 32 # => 0 # 8000 << -1 # => 4000 # ``` def <<(count : Int) if count < 0 self >> count.abs elsif count < sizeof(self) * 8 self.unsafe_shl(count) else self.class.zero end end def <=>(other : Int) : Int32 # Override Number#<=> because when comparing # Int vs Int there's no way we can return `nil` self > other ? 1 : (self < other ? -1 : 0) end def abs : self self >= 0 ? self : -self end def round(mode : RoundingMode) : self self end def ceil : self self end def floor : self self end def trunc : self self end # Returns `self`. def round_even : self self end # Returns `self`. def round_away self end # :inherit: # # Always returns `true` for `Int`. def integer? : Bool true end # Returns the value of raising `self` to the power of *exponent*. # # Raises `ArgumentError` if *exponent* is negative: if this is needed, # either use a float base or a float exponent. # # Raises `OverflowError` in case of overflow. # # ``` # 2 ** 3 # => 8 # 2 ** 0 # => 1 # 2 ** -1 # ArgumentError # ``` def **(exponent : Int) : self if exponent < 0 raise ArgumentError.new "Cannot raise an integer to a negative integer power, use floats for that" end result = self.class.new(1) k = self while exponent > 0 result *= k if exponent & 0b1 != 0 exponent = exponent.unsafe_shr(1) k *= k if exponent > 0 end result end # Returns the value of raising `self` to the power of *exponent*. # # Raises `ArgumentError` if *exponent* is negative: if this is needed, # either use a float base or a float exponent. # # Intermediate multiplication will wrap around silently in case of overflow. # # ``` # 2 &** 3 # => 8 # 2 &** 0 # => 1 # 2 &** -1 # ArgumentError # ``` def &**(exponent : Int) : self if exponent < 0 raise ArgumentError.new "Cannot raise an integer to a negative integer power, use floats for that" end result = self.class.new(1) k = self while exponent > 0 result &*= k if exponent & 0b1 != 0 exponent = exponent.unsafe_shr(1) k &*= k if exponent > 0 end result end # Returns the value of raising `self` to the power of *exponent*. # # ``` # 2 ** 3.0 # => 8.0 # 2 ** 0.0 # => 1.0 # 2 ** -1.0 # => 0.5 # ``` def **(exponent : Float) : Float64 to_f ** exponent end def ===(char : Char) self === char.ord end # Returns this number's *bit*th bit, starting with the least-significant. # # ``` # 11.bit(0) # => 1 # 11.bit(1) # => 1 # 11.bit(2) # => 0 # 11.bit(3) # => 1 # 11.bit(4) # => 0 # ``` def bit(bit) self >> bit & 1 end # Returns the requested range of bits # # ``` # 0b10011.bits(0..1) # => 0b11 # 0b10011.bits(0..2) # => 0b11 # 0b10011.bits(0..3) # => 0b11 # 0b10011.bits(0..4) # => 0b10011 # 0b10011.bits(0..5) # => 0b10011 # 0b10011.bits(1..4) # => 0b1001 # ``` def bits(range : Range) start_index = range.begin if start_index raise IndexError.new("Start index (#{start_index}) must be positive") if start_index < 0 else start_index = 0 end end_index = range.end if end_index raise IndexError.new("End index (#{end_index}) must be positive") if end_index < 0 end_index += 1 unless range.exclusive? raise IndexError.new("End index (#{end_index}) must be greater than start index (#{start_index})") if end_index <= start_index else # if there is no end index then we only need to shift return self >> start_index end # Generates a mask `count` bits long maintaining the correct type count = end_index - start_index mask = (self.class.new(1) << count) &- 1 if self < 0 # Special case for negative to ensure the shift and mask work as expected # The result is always negative offset = (~self) >> start_index result = offset & mask ~result else # Shifts out the bits we want to ignore before applying the mask offset = self >> start_index offset & mask end end # Returns `true` if all bits in *mask* are set on `self`. # # ``` # 0b0110.bits_set?(0b0110) # => true # 0b1101.bits_set?(0b0111) # => false # 0b1101.bits_set?(0b1100) # => true # ``` def bits_set?(mask) : Bool (self & mask) == mask end # Returns the number of bits of this int value. # # “The number of bits” means that the bit position of the highest bit # which is different to the sign bit. # (The bit position of the bit 2**n is n+1.) # If there is no such bit (zero or minus one), zero is returned. # # I.e. This method returns `ceil(log2(self < 0 ? -self : self + 1))`. # # ``` # 0.bit_length # => 0 # 1.bit_length # => 1 # 2.bit_length # => 2 # 3.bit_length # => 2 # 4.bit_length # => 3 # 5.bit_length # => 3 # # # The above is the same as # 0b0.bit_length # => 0 # 0b1.bit_length # => 1 # 0b10.bit_length # => 2 # 0b11.bit_length # => 2 # 0b100.bit_length # => 3 # 0b101.bit_length # => 3 # ``` def bit_length : Int32 x = self < 0 ? ~self : self if x.is_a?(Int::Primitive) Int32.new(sizeof(self) * 8 - x.leading_zeros_count) else # Safe fallback for any non-primitive Int type to_s(2).size end end # :nodoc: def next_power_of_two : self one = self.class.new!(1) bits = sizeof(self) * 8 shift = bits &- (self &- 1).leading_zeros_count if self.is_a?(Int::Signed) shift = 0 if shift >= bits &- 1 else shift = 0 if shift == bits end result = one << shift result >= self ? result : raise OverflowError.new end # Returns the greatest common divisor of `self` and *other*. Signed # integers may raise `OverflowError` if either has value equal to `MIN` of # its type. # # ``` # 5.gcd(10) # => 5 # 5.gcd(7) # => 1 # ``` def gcd(other : self) : self # Implementation heavily inspired by # https://en.wikipedia.org/wiki/Binary_GCD_algorithm#Iterative_version_in_C u = self.abs v = other.abs return v if u == 0 return u if v == 0 # Let shift := lg K, where K is the greatest power of 2 # dividing both u and v. shift = (u | v).trailing_zeros_count u = u.unsafe_shr(u.trailing_zeros_count) # From here on, u is always odd. loop do # remove all factors of 2 in v -- they are not common v = v.unsafe_shr(v.trailing_zeros_count) # Now u and v are both odd. Swap if necessary so u <= v, # then set v = v - u (which is even). u, v = v, u if u > v v &-= u break if v.zero? end # restore common factors of 2 u.unsafe_shl shift end # Returns the least common multiple of `self` and *other*. # # Raises `OverflowError` in case of overflow. def lcm(other : Int) (self // gcd(other) * other).abs end def divisible_by?(num) : Bool remainder(num) == 0 end def even? : Bool divisible_by? 2 end def odd? : Bool !even? end def succ : self self + 1 end def pred : self self - 1 end def times(&block : self ->) : Nil i = self ^ self while i < self yield i i &+= 1 end end def times TimesIterator(typeof(self)).new(self) end def upto(to, &block : self ->) : Nil return unless self <= to x = self while true yield x return unless x < to x += 1 end end def upto(to) UptoIterator(typeof(self), typeof(to)).new(self, to) end # Calls the given block with each integer value from self down to `to`. # # ``` # 3.downto(1) do |i| # puts i # end # ``` # # Prints: # # ```text # 3 # 2 # 1 # ``` def downto(to, &block : self ->) : Nil return unless self >= to x = self while true yield x return unless x > to x -= 1 end end # Get an iterator for counting down from self to `to`. def downto(to) DowntoIterator(typeof(self), typeof(to)).new(self, to) end def to(to, &block : self ->) : Nil if self < to upto(to) { |i| yield i } elsif self > to downto(to) { |i| yield i } else yield self end end def to(to) self <= to ? upto(to) : downto(to) end def modulo(other) self % other end # Returns the digits of a number in a given base. # The digits are returned as an array with the least significant digit as the first array element. # # ``` # 12345.digits # => [5, 4, 3, 2, 1] # 12345.digits(7) # => [4, 6, 6, 0, 5] # 12345.digits(100) # => [45, 23, 1] # # -12345.digits(7) # => ArgumentError # ``` def digits(base = 10) : Array(Int32) if base < 2 raise ArgumentError.new("Invalid base #{base}") end if self < 0 raise ArgumentError.new("Can't request digits of negative number") end if self == 0 return [0] end num = self digits_count = (Math.log(self.to_f + 1) / Math.log(base)).ceil.to_i ary = Array(Int32).new(digits_count) while num != 0 ary << num.remainder(base).to_i num = num.tdiv(base) end ary end private DIGITS_DOWNCASE = "0123456789abcdefghijklmnopqrstuvwxyz" private DIGITS_UPCASE = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" private DIGITS_BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" # Returns a string representation of this integer. # # *base* specifies the radix of the returned string, and must be either 62 or # a number between 2 and 36. By default, digits above 9 are represented by # ASCII lowercase letters (`a` for 10, `b` for 11, etc.), but uppercase # letters may be used if *upcase* is `true`, unless base 62 is used. In that # case, lowercase letters are used for 10 to 35, and uppercase ones for 36 to # 61, and *upcase* must be `false`. # # *precision* specifies the minimum number of digits in the returned string. # If there are fewer digits than this number, the string is left-padded by # zeros. If `self` and *precision* are both zero, returns an empty string. # # ``` # 1234.to_s # => "1234" # 1234.to_s(2) # => "10011010010" # 1234.to_s(16) # => "4d2" # 1234.to_s(16, upcase: true) # => "4D2" # 1234.to_s(36) # => "ya" # 1234.to_s(62) # => "jU" # 1234.to_s(precision: 2) # => "1234" # 1234.to_s(precision: 6) # => "001234" # ``` def to_s(base : Int = 10, *, precision : Int = 1, upcase : Bool = false) : String raise ArgumentError.new("Invalid base #{base}") unless 2 <= base <= 36 || base == 62 raise ArgumentError.new("upcase must be false for base 62") if upcase && base == 62 raise ArgumentError.new("Precision must be non-negative") unless precision >= 0 case {self, precision} when {0, 0} "" when {0, 1} "0" when {1, 1} "1" else internal_to_s(base, precision, upcase) do |ptr, count, negative| # reuse the `chars` buffer in `internal_to_s` if possible if precision <= count || precision <= 128 if precision > count difference = precision - count ptr -= difference Slice.new(ptr, difference).fill('0'.ord.to_u8) count += difference end if negative ptr -= 1 ptr.value = '-'.ord.to_u8 count += 1 end String.new(ptr, count, count) else len = precision + (negative ? 1 : 0) String.new(len) do |buffer| if negative buffer.value = '-'.ord.to_u8 buffer += 1 end Slice.new(buffer, precision - count).fill('0'.ord.to_u8) ptr.copy_to(buffer + precision - count, count) {len, len} end end end end end # Appends a string representation of this integer to the given *io*. # # *base* specifies the radix of the written string, and must be either 62 or # a number between 2 and 36. By default, digits above 9 are represented by # ASCII lowercase letters (`a` for 10, `b` for 11, etc.), but uppercase # letters may be used if *upcase* is `true`, unless base 62 is used. In that # case, lowercase letters are used for 10 to 35, and uppercase ones for 36 to # 61, and *upcase* must be `false`. # # *precision* specifies the minimum number of digits in the written string. # If there are fewer digits than this number, the string is left-padded by # zeros. If `self` and *precision* are both zero, returns an empty string. def to_s(io : IO, base : Int = 10, *, precision : Int = 1, upcase : Bool = false) : Nil raise ArgumentError.new("Invalid base #{base}") unless 2 <= base <= 36 || base == 62 raise ArgumentError.new("upcase must be false for base 62") if upcase && base == 62 raise ArgumentError.new("Precision must be non-negative") unless precision >= 0 case {self, precision} when {0, 0} # do nothing when {0, 1} io << '0' when {1, 1} io << '1' else internal_to_s(base, precision, upcase) do |ptr, count, negative| io << '-' if negative if precision > count (precision - count).times { io << '0' } end io.write_string Slice.new(ptr, count) end end end private def internal_to_s(base, precision, upcase = false, &) # Given sizeof(self) <= 128 bits, we need at most 128 bytes for a base 2 # representation, plus one byte for the negative sign (possibly used by the # string-returning overload). chars = uninitialized UInt8[129] ptr_end = chars.to_unsafe + 129 ptr = ptr_end num = self neg = num < 0 digits = (base == 62 ? DIGITS_BASE62 : (upcase ? DIGITS_UPCASE : DIGITS_DOWNCASE)).to_unsafe while num != 0 ptr -= 1 ptr.value = digits[num.remainder(base).abs] num = num.tdiv(base) end count = (ptr_end - ptr).to_i32 yield ptr, count, neg end # Writes this integer to the given *io* in the given *format*. # # See also: `IO#write_bytes`. def to_io(io : IO, format : IO::ByteFormat) : Nil format.encode(self, io) end # Reads an integer from the given *io* in the given *format*. # # See also: `IO#read_bytes`. def self.from_io(io : IO, format : IO::ByteFormat) : self format.decode(self, io) end # Counts `1`-bits in the binary representation of this integer. # # ``` # 5.popcount # => 2 # -15.popcount # => 29 # ``` abstract def popcount # Returns the number of trailing `0`-bits. abstract def trailing_zeros_count private class TimesIterator(T) include Iterator(T) @n : T @index : T def initialize(@n : T, @index = T.zero) end def next if @index < @n value = @index @index &+= 1 value else stop end end end private class UptoIterator(T, N) include Iterator(T) @from : T @to : N @current : T @done : Bool def initialize(@from : T, @to : N) @current = @from @done = !(@from <= @to) end def next return stop if @done value = @current @done = @current == @to @current += 1 unless @done value end end private class DowntoIterator(T, N) include Iterator(T) @from : T @to : N @current : T @done : Bool def initialize(@from : T, @to : N) @current = @from @done = !(@from >= @to) end def next return stop if @done value = @current @done = @current == @to @current -= 1 unless @done value end end end struct Int8 MIN = -128_i8 MAX = 127_i8 # Returns an `Int8` by invoking `to_i8` on *value*. # See `String#to_i` for more details. # # ``` # Int8.new "20" # => 20 # Int8.new " 20 ", whitespace: false # raises ArgumentError: Invalid Int8: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_i8 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `Int8` by invoking `to_i8` on *value*. def self.new(value) : self value.to_i8 end # Returns an `Int8` by invoking `to_i8!` on *value*. def self.new!(value) : self value.to_i8! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def - : Int8 0_i8 - self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int8 self end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int8 self end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt8 to_u8 end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt8 to_u8! end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : UInt8 self < 0 ? 0_u8 &- self : to_u8! end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : self -self end def popcount : Int8 Intrinsics.popcount8(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse8(self).to_i8! end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x12_i8.byte_swap # => 0x12 # ``` def byte_swap : self self end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading8(self, false) end def trailing_zeros_count Intrinsics.counttrailing8(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl8(self, self, n.to_i8!).to_i8! end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr8(self, self, n.to_i8!).to_i8! end def clone self end end struct Int16 MIN = -32768_i16 MAX = 32767_i16 # Returns an `Int16` by invoking `to_i16` on *value*. # See `String#to_i` for more details. # # ``` # Int16.new "20" # => 20 # Int16.new " 20 ", whitespace: false # raises ArgumentError: Invalid Int16: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_i16 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `Int16` by invoking `to_i16` on *value*. def self.new(value) : self value.to_i16 end # Returns an `Int16` by invoking `to_i16!` on *value*. def self.new!(value) : self value.to_i16! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def - : Int16 0_i16 - self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int16 self end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int16 self end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt16 to_u16 end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt16 to_u16! end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : UInt16 self < 0 ? 0_u16 &- self : to_u16! end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : self -self end def popcount : Int16 Intrinsics.popcount16(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse16(self).to_i16! end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x1234_i16.byte_swap # => 0x3412 # ``` def byte_swap : self Intrinsics.bswap16(self).to_i16! end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading16(self, false) end def trailing_zeros_count Intrinsics.counttrailing16(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl16(self, self, n.to_i16!).to_i16! end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr16(self, self, n.to_i16!).to_i16! end def clone self end end struct Int32 MIN = -2147483648_i32 MAX = 2147483647_i32 # Returns an `Int32` by invoking `to_i32` on *value*. # See `String#to_i` for more details. # # ``` # Int32.new "20" # => 20 # Int32.new " 20 ", whitespace: false # raises ArgumentError: Invalid Int32: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_i32 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `Int32` by invoking `to_i32` on *value*. def self.new(value) : self value.to_i32 end # Returns an `Int32` by invoking `to_i32!` on *value*. def self.new!(value) : self value.to_i32! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def - : Int32 0 - self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int32 self end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int32 self end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt32 to_u32 end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt32 to_u32! end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : UInt32 self < 0 ? 0_u32 &- self : to_u32! end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : self -self end def popcount : Int32 Intrinsics.popcount32(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse32(self).to_i32! end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x12345678_i32.byte_swap # => 0x78563412 # ``` def byte_swap : self Intrinsics.bswap32(self).to_i32! end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading32(self, false) end def trailing_zeros_count Intrinsics.counttrailing32(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl32(self, self, n.to_i32!).to_i32! end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr32(self, self, n.to_i32!).to_i32! end def clone self end end struct Int64 MIN = -9223372036854775808_i64 MAX = 9223372036854775807_i64 # Returns an `Int64` by invoking `to_i64` on *value*. # See `String#to_i` for more details. # # ``` # Int64.new "20" # => 20 # Int64.new " 20 ", whitespace: false # raises ArgumentError: Invalid Int64: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_i64 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `Int64` by invoking `to_i64` on *value*. def self.new(value) : self value.to_i64 end # Returns an `Int64` by invoking `to_i64!` on *value*. def self.new!(value) : self value.to_i64! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def - : Int64 0_i64 - self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int64 self end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int64 self end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt64 to_u64 end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt64 to_u64! end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : UInt64 self < 0 ? 0_u64 &- self : to_u64! end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : self -self end def popcount : Int64 Intrinsics.popcount64(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse64(self).to_i64! end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x12345678_i64.byte_swap # => 0x7856341200000000 # 0x123456789ABCDEF0_i64.byte_swap # => -0xf21436587a9cbee # ``` def byte_swap : self Intrinsics.bswap64(self).to_i64! end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading64(self, false) end def trailing_zeros_count Intrinsics.counttrailing64(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl64(self, self, n.to_i64!).to_i64! end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr64(self, self, n.to_i64!).to_i64! end def clone self end end struct Int128 # TODO: eventually update to literals once UInt128 bit support is finished MIN = new(1) << 127 MAX = ~MIN # Returns an `Int128` by invoking `to_i128` on *value*. # See `String#to_i` for more details. # # ``` # Int128.new "20" # => 20 # Int128.new " 20 ", whitespace: false # raises ArgumentError: Invalid Int128: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_i128 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `Int128` by invoking `to_i128` on *value*. def self.new(value) : self value.to_i128 end # Returns an `Int128` by invoking `to_i128!` on *value*. def self.new!(value) : self value.to_i128! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def - # TODO: use 0_i128 - self Int128.new(0) - self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int128 self end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int128 self end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt128 to_u128 end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt128 to_u128! end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : UInt128 self < 0 ? UInt128.new(0) &- self : to_u128! end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : self -self end def popcount Intrinsics.popcount128(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse128(self).to_i128! end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x123456789_i128.byte_swap # => -0x7698badcff0000000000000000000000 # ``` def byte_swap : self Intrinsics.bswap128(self).to_i128! end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading128(self, false) end def trailing_zeros_count Intrinsics.counttrailing128(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl128(self, self, n.to_i128!).to_i128! end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr128(self, self, n.to_i128!).to_i128! end def clone self end end struct UInt8 MIN = 0_u8 MAX = 255_u8 # Returns an `UInt8` by invoking `to_u8` on *value*. # See `String#to_i` for more details. # # ``` # UInt8.new "20" # => 20 # UInt8.new " 20 ", whitespace: false # raises ArgumentError: Invalid UInt8: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_u8 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `UInt8` by invoking `to_u8` on *value*. def self.new(value) : self value.to_u8 end # Returns an `UInt8` by invoking `to_u8!` on *value*. def self.new!(value) : self value.to_u8! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def &- : UInt8 0_u8 &- self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int8 to_i8 end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int8 to_i8! end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt8 self end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt8 self end def abs : self self end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : self self end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : Int8 0_i8 - self end def popcount : Int8 Intrinsics.popcount8(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse8(self) end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x12_u8.byte_swap # => 0x12 # ``` def byte_swap : self self end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading8(self, false) end def trailing_zeros_count Intrinsics.counttrailing8(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl8(self, self, n.to_u8!) end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr8(self, self, n.to_u8!) end def clone self end end struct UInt16 MIN = 0_u16 MAX = 65535_u16 # Returns an `UInt16` by invoking `to_u16` on *value*. # See `String#to_i` for more details. # # ``` # UInt16.new "20" # => 20 # UInt16.new " 20 ", whitespace: false # raises ArgumentError: Invalid UInt16: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_u16 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `UInt16` by invoking `to_u16` on *value*. def self.new(value) : self value.to_u16 end # Returns an `UInt16` by invoking `to_u16!` on *value*. def self.new!(value) : self value.to_u16! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def &- : UInt16 0_u16 &- self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int16 to_i16 end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int16 to_i16! end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt16 self end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt16 self end def abs : self self end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : self self end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : Int16 0_i16 - self end def popcount : Int16 Intrinsics.popcount16(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse16(self) end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x1234_u16.byte_swap # => 0x3412 # ``` def byte_swap : self Intrinsics.bswap16(self) end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading16(self, false) end def trailing_zeros_count Intrinsics.counttrailing16(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl16(self, self, n.to_u16!) end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr16(self, self, n.to_u16!) end def clone self end end struct UInt32 MIN = 0_u32 MAX = 4294967295_u32 # Returns an `UInt32` by invoking `to_u32` on *value*. # See `String#to_i` for more details. # # ``` # UInt32.new "20" # => 20 # UInt32.new " 20 ", whitespace: false # raises ArgumentError: Invalid UInt32: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_u32 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `UInt32` by invoking `to_u32` on *value*. def self.new(value) : self value.to_u32 end # Returns an `UInt32` by invoking `to_u32!` on *value*. def self.new!(value) : self value.to_u32! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def &- : UInt32 0_u32 &- self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int32 to_i32 end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int32 to_i32! end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt32 self end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt32 self end def abs : self self end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : self self end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : Int32 0_i32 - self end def popcount : Int32 Intrinsics.popcount32(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse32(self) end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x12345678_u32.byte_swap # => 0x78563412 # ``` def byte_swap : self Intrinsics.bswap32(self) end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading32(self, false) end def trailing_zeros_count Intrinsics.counttrailing32(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl32(self, self, n.to_u32!) end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr32(self, self, n.to_u32!) end def clone self end end struct UInt64 MIN = 0_u64 MAX = 18446744073709551615_u64 # Returns an `UInt64` by invoking `to_u64` on *value*. # See `String#to_i` for more details. # # ``` # UInt64.new "20" # => 20 # UInt64.new " 20 ", whitespace: false # raises ArgumentError: Invalid UInt64: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_u64 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `UInt64` by invoking `to_u64` on *value*. def self.new(value) : self value.to_u64 end # Returns an `UInt64` by invoking `to_u64!` on *value*. def self.new!(value) : self value.to_u64! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def &- : UInt64 0_u64 &- self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int64 to_i64 end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int64 to_i64! end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt64 self end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt64 self end def abs : self self end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : self self end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : Int64 0_i64 - self end def popcount : Int64 Intrinsics.popcount64(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse64(self) end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x123456789ABCDEF0_u64.byte_swap # => 0xF0DEBC9A78563412 # ``` def byte_swap : self Intrinsics.bswap64(self) end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading64(self, false) end def trailing_zeros_count Intrinsics.counttrailing64(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl64(self, self, n.to_u64!) end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr64(self, self, n.to_u64!) end def clone self end end struct UInt128 # TODO: eventually update to literals once UInt128 bit support is finished MIN = new 0 MAX = ~MIN # Returns an `UInt128` by invoking `to_u128` on *value*. # See `String#to_i` for more details. # # ``` # UInt128.new "20" # => 20 # UInt128.new " 20 ", whitespace: false # raises ArgumentError: Invalid UInt128: " 20 " # ``` def self.new(value : String, base : Int = 10, whitespace : Bool = true, underscore : Bool = false, prefix : Bool = false, strict : Bool = true, leading_zero_is_octal : Bool = false) : self value.to_u128 base: base, whitespace: whitespace, underscore: underscore, prefix: prefix, strict: strict, leading_zero_is_octal: leading_zero_is_octal end # Returns an `UInt128` by invoking `to_u128` on *value*. def self.new(value) : self value.to_u128 end # Returns an `UInt128` by invoking `to_u128!` on *value*. def self.new!(value) : self value.to_u128! end Number.expand_div [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128], Float64 Number.expand_div [Float32], Float32 Number.expand_div [Float64], Float64 def &- # TODO: use 0_u128 &- self UInt128.new(0) &- self end # Returns `self` converted to a signed value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # Raises `OverflowError` in case of overflow. # # ``` # 1_u32.to_signed # => 1_i32 # 2_u16.to_signed # => 2_i16 # 3_i64.to_signed # => 3_i64 # ``` def to_signed : Int128 to_i128 end # Returns `self` converted to a signed value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Signed`. # # ``` # 1_u32.to_signed! # => 1_i32 # 65530_u16.to_signed! # => -6_i16 # 3_i64.to_signed! # => 3_i64 # ``` def to_signed! : Int128 to_i128! end # Returns `self` converted to an unsigned value of the same size. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # Raises `OverflowError` in case of overflow. # # ``` # 1_i32.to_unsigned # => 1_u32 # 2_i16.to_unsigned # => 2_u16 # 3_u64.to_unsigned # => 3_u64 # ``` def to_unsigned : UInt128 self end # Returns `self` converted to an unsigned value of the same size, wrapping in # case of overflow. # # Simply returns `self` unmodified if `self` is already an `Int::Unsigned`. # # ``` # 1_i32.to_unsigned! # => 1_u32 # (-6_i16).to_unsigned! # => 65530_u16 # 3_u64.to_unsigned! # => 3_u64 # ``` def to_unsigned! : UInt128 self end def abs self end # Returns the absolute value of `self` as an unsigned value of the same size. # # Returns `self` if `self` is already an `Int::Unsigned`. This method never # overflows. # # ``` # 1_u32.abs_unsigned # => 1_u32 # 2_i32.abs_unsigned # => 2_u32 # -3_i8.abs_unsigned # => 3_u8 # Int16::MIN.abs_unsigned # => 32768_u16 # ``` def abs_unsigned : self self end # Returns the negative of `self` as a signed value of the same size. # # Returns `-self` if `self` is already an `Int::Signed`. Raises # `OverflowError` in case of overflow. # # ``` # 1_i32.neg_signed # => -1_i32 # 2_u16.neg_signed # => -2_i16 # 128_u8.neg_signed # => -128_i8 # Int16::MIN.neg_signed # raises OverflowError # ``` def neg_signed : Int128 Int128.new(0) - self end def popcount Intrinsics.popcount128(self) end # Reverses the bits of `self`; the least significant bit becomes the most # significant, and vice-versa. # # ``` # 0b01001011_u8.bit_reverse # => 0b11010010 # 0b1100100001100111_u16.bit_reverse # => 0b1110011000010011 # ``` def bit_reverse : self Intrinsics.bitreverse128(self) end # Swaps the bytes of `self`; a little-endian value becomes a big-endian value, # and vice-versa. The bit order within each byte is unchanged. # # Has no effect on 8-bit integers. # # ``` # 0x123456789ABCDEF013579BDF2468ACE0_u128.byte_swap # => 0xE0AC6824DF9B5713F0DEBC9A78563412 # ``` def byte_swap : self Intrinsics.bswap128(self) end # Returns the number of leading `0`-bits. def leading_zeros_count Intrinsics.countleading128(self, false) end def trailing_zeros_count Intrinsics.counttrailing128(self, false) end # Returns the bitwise rotation of `self` *n* times in the most significant # bit's direction. Negative shifts are equivalent to `rotate_right(-n)`. # # ``` # 0b01001101_u8.rotate_left(3) # => 0b01101010 # 0b01001101_u8.rotate_left(8) # => 0b01001101 # 0b01001101_u8.rotate_left(11) # => 0b01101010 # 0b01001101_u8.rotate_left(-1) # => 0b10100110 # ``` def rotate_left(n : Int) : self Intrinsics.fshl128(self, self, n.to_u128!) end # Returns the bitwise rotation of `self` *n* times in the least significant # bit's direction. Negative shifts are equivalent to `rotate_left(-n)`. # # ``` # 0b01001101_u8.rotate_right(3) # => 0b10101001 # 0b01001101_u8.rotate_right(8) # => 0b01001101 # 0b01001101_u8.rotate_right(11) # => 0b10101001 # 0b01001101_u8.rotate_right(-1) # => 0b10011010 # ``` def rotate_right(n : Int) : self Intrinsics.fshr128(self, self, n.to_u128!) end def clone self end end {% for type in %w(Int8 Int16 Int32 Int64 Int128 UInt8 UInt16 UInt32 UInt64 UInt128) %} # Returns a number for given digits and base. # The digits are expected as an `Enumerable` with the least significant digit as the first element. # # Base must not be less than 2. # # All digits must be within 0...base. # # ``` # {{type.id}}.from_digits([5, 4, 3, 2, 1]) # => 12345 # {{type.id}}.from_digits([4, 6, 6, 0, 5], base: 7) # => 12345 # {{type.id}}.from_digits([45, 23, 1], base: 100) # => 12345 # # {{type.id}}.from_digits([1], base: -2) # raises ArgumentError # {{type.id}}.from_digits([-1]) # raises ArgumentError # {{type.id}}.from_digits([3], base: 2) # raises ArgumentError # ``` def {{type.id}}.from_digits(digits : Enumerable(Int), base : Int = 10) : self if base < 2 raise ArgumentError.new("Invalid base #{base}") end num : {{type.id}} = 0 multiplier : {{type.id}} = 1 first_element = true digits.each do |digit| if digit < 0 raise ArgumentError.new("Invalid digit #{digit}") end if digit >= base raise ArgumentError.new("Invalid digit #{digit} for base #{base}") end # don't calculate multiplier upfront for the next digit # to avoid overflow at the last iteration if first_element first_element = false else multiplier *= base end num += digit * multiplier end num end {% end %}