Class: BitInt::Base Abstract
- Inherits:
-
Numeric
- Object
- Numeric
- BitInt::Base
- Defined in:
- lib/bitint/base.rb
Overview
Subclasses must be created via ‘Base.create`
Class Method Summary collapse
-
.create(bits: nil, bytes: nil, signed:) ⇒ singleton(Base)
Creates a new Base subclass.
-
.in_bounds?(integer) ⇒ bool
abstract
Check to see if
integeris in bounds forself. -
.inspect ⇒ Object
(also: to_s)
Returns a debugging string representation of this class.
-
.signed? ⇒ Boolean
abstract
Returns whether this class represents a signed integer.
-
.unsigned? ⇒ Boolean
abstract
Returns whether this class represents an unsigned integer.
-
.wrap(integer) ⇒ Integer
abstract
Wraps an
integerto be within the bounds ofself.
Instance Method Summary collapse
-
#%(rhs) ⇒ Object
Modulos
selfbyrhs. -
#&(rhs) ⇒ Object
Bitwise ANDs
selfandrhs. -
#*(rhs) ⇒ Object
Multiplies
selfbyrhs. -
#**(rhs) ⇒ Object
Raises
selfto the rhsth power. -
#+(rhs) ⇒ Object
Adds
selftorhs. -
#-(rhs) ⇒ Object
Subtracts
rhsfromself. -
#-@ ⇒ Object
Numerically negates
self. -
#/(rhs) ⇒ Object
Divides
selfbyrhs. -
#<<(rhs) ⇒ Object
Shifts
selfleft byrhsbits. -
#<=>(rhs) ⇒ Object
Compares
selftorhs. -
#==(rhs) ⇒ Object
Checks to see if
rhsis equal toselF. -
#>>(rhs) ⇒ Object
Shifts
selfright byrhsbits. -
#[] ⇒ Object
Gets the bit at index
idxor returnsnil. -
#^(rhs) ⇒ Object
Bitwise XORs
selfandrhs. -
#allbits?(mask) ⇒ Boolean
Returns true if all bits in ‘mask` are set in
self. -
#anybits?(mask) ⇒ Boolean
Returns true if any bit in ‘mask` is set in
self. -
#bin ⇒ Object
Returns a base-2 string of
self. -
#bit_length ⇒ Object
Returns the amount of bits required to represent
self. -
#byte_length ⇒ Object
Returns the amount of bytes required to represent
self. -
#bytes(endian = :native) ⇒ Object
Returns all the bytes that’re used represent
self. -
#coerce(other) ⇒ Object
Converts
otherto an instance ofself, and returns a tuple of [<converted>, self]. -
#downto(what) ⇒ Object
Same as Integer#downto, but returns instances of
self. -
#each_byte(endian = :native) ⇒ Object
Executes the block once for each byte in
self. -
#eql?(rhs) ⇒ Boolean
Checks to see if
rhsis anotherBitInt::Baseof the same class, and have the same contents. -
#even? ⇒ Boolean
Checks to see if
selfis even. -
#hash ⇒ Object
Returns a hash code for this class.
-
#hex(upper: false) ⇒ Object
Returns a base-16 string of
self. -
#initialize(integer, wrap: true) ⇒ Base
constructor
Creates a new instance with the
integer. -
#integer? ⇒ Boolean
Always return
true, as BitInt::Bases are always integers. -
#negative? ⇒ Boolean
Return whether
selfis a negative integer. -
#nobits?(mask) ⇒ Boolean
Returns true if no bits in ‘mask` are set in
self. -
#nonzero? ⇒ Boolean
Returns a falsey value if zero, otherwise returns
self. -
#oct ⇒ Object
Returns a base-8 string of
self. -
#odd? ⇒ Boolean
Checks to see if
selfis odd. -
#positive? ⇒ Boolean
Returns whether
selfis a positive integer. -
#pred ⇒ Object
Gets the next value, or throws a OverFlowError if at the top.
-
#succ ⇒ Object
Gets the next value, or throws a OverFlowError if at the top.
-
#times ⇒ Object
Same as Integer#times, but returns instances of
self. -
#to_f ⇒ Object
Converts
selfto aFloat. -
#to_i ⇒ Object
(also: #to_int)
Returns the underlying integer.
-
#to_r ⇒ Object
Converts
selfto aRational. -
#to_s(base = nil) ⇒ Object
(also: #inspect)
Converts
selfto aString. -
#upto(what) ⇒ Object
Same as Integer#downto, but returns instances of
self. -
#zero? ⇒ Boolean
Returns whether
selfis zero. -
#|(rhs) ⇒ Object
Bitwise ORs
selfandrhs. -
#~ ⇒ Object
Bitwise negates
self.
Constructor Details
#initialize(integer, wrap: true) ⇒ Base
Creates a new instance with the integer.
Example
puts BitInt::U8.new(27) #=> 27
puts BitInt::U8.new(-1) #=> 255
puts BitInt::U8.new(-1, wrap: false) #=> OverflowError
puts BitInt::I8.new(255) #=> -1
174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/bitint/base.rb', line 174 def initialize(integer, wrap: true) unless wrap || self.class.in_bounds?(integer) exc = OverflowError.new(integer, self.class::BOUNDS) exc.set_backtrace( caller_locations(1) #: Array[Thread::Backtrace::Location] ) raise exc end @int = self.class.wrap(integer) @wrap = wrap end |
Class Method Details
.create(bits: nil, bytes: nil, signed:) ⇒ singleton(Base)
Creates a new BitInt::Base subclass.
Example
puts BitInt::Base.create(bits: 8, signed: true).new(128) #=> -127
puts BitInt::Base.create(bytes: 1, signed: false).new(256) #=> 0
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/bitint/base.rb', line 47 def create(bits: nil, bytes: nil, signed:) if bits.nil? == bytes.nil? raise ArgumentError, "exactly one of 'bits' or 'bytes' must be supplied", caller(1) end bits ||= (_ = bytes) * 8 unless bits.positive? raise ArgumentError, 'bit count must be positive', caller(1) end key = [bits, signed].freeze #: [Integer, bool] @classes[key] ||= Class.new(Base) do |cls| (_ = cls).setup!(bits, signed) end end |
.in_bounds?(integer) ⇒ bool
Only defined on subclasses
Check to see if integer is in bounds for self
Example
puts BitInt::I16.in_bounds?(32767) #=> true
puts BitInt::I16.in_bounds?(32768) #=> false
puts BitInt::U32.in_bounds?(-1) #=> false
154 155 156 157 |
# File 'lib/bitint/base.rb', line 154 def in_bounds?(integer) # TODO: use `self::BOUNDS` (self::MIN.to_i .. self::MAX.to_i).include? integer end |
.inspect ⇒ Object Also known as: to_s
Returns a debugging string representation of this class
If the class is one of the builtins (eg BitInt::U16), it uses its name as the string, otherwise it uses a debugging representation
Example
p BitInt::U16 #=> BitInt::U16
p BitInt::U(17) #=> #<BitInt::Base @bits=17 @signed=false>
121 |
# File 'lib/bitint/base.rb', line 121 def inspect = name || "#<BitInt::Base @bits=#@bits @signed=#@signed>" |
.signed? ⇒ Boolean
Only defined on subclasses
Returns whether this class represents a signed integer.
Example
puts BitInt::U8.signed? #=> false
puts BitInt::I8.signed? #=> true
98 |
# File 'lib/bitint/base.rb', line 98 def signed? = @signed |
.unsigned? ⇒ Boolean
Only defined on subclasses
Returns whether this class represents an unsigned integer.
Example
puts BitInt::U8.unsigned? #=> true
puts BitInt::I8.unsigned? #=> false
109 |
# File 'lib/bitint/base.rb', line 109 def unsigned? = !signed? |
.wrap(integer) ⇒ Integer
Only defined on subclasses
Wraps an integer to be within the bounds of self
Example
puts BitInt::I8.wrap(127) #=> 127
puts BitInt::I8.wrap(128) #=> -128
puts BitInt::I8.wrap(0xFF_FF_FF_FF_FF) #=> -1
137 138 139 |
# File 'lib/bitint/base.rb', line 137 def wrap(integer) ((integer - self::MIN.to_i) & self::MASK) + self::MIN.to_i end |
Instance Method Details
#%(rhs) ⇒ Object
Modulos self by rhs.
344 |
# File 'lib/bitint/base.rb', line 344 def %(rhs) = new_instance(@int % rhs.to_int) |
#&(rhs) ⇒ Object
Bitwise ANDs self and rhs.
465 |
# File 'lib/bitint/base.rb', line 465 def &(rhs) = new_instance(@int & rhs.to_int) |
#*(rhs) ⇒ Object
Multiplies self by rhs.
334 |
# File 'lib/bitint/base.rb', line 334 def *(rhs) = new_instance(@int * rhs.to_int) |
#**(rhs) ⇒ Object
Raises self to the rhsth power.
349 |
# File 'lib/bitint/base.rb', line 349 def **(rhs) = new_instance((@int ** rhs.to_int).to_int) # TODO: use `Integer#pow(int, int)` |
#+(rhs) ⇒ Object
Adds self to rhs.
324 |
# File 'lib/bitint/base.rb', line 324 def +(rhs) = new_instance(@int + rhs.to_int) |
#-(rhs) ⇒ Object
Subtracts rhs from self.
329 |
# File 'lib/bitint/base.rb', line 329 def -(rhs) = new_instance(@int - rhs.to_int) |
#-@ ⇒ Object
Numerically negates self.
313 |
# File 'lib/bitint/base.rb', line 313 def -@ = new_instance(-@int) |
#/(rhs) ⇒ Object
Divides self by rhs.
339 |
# File 'lib/bitint/base.rb', line 339 def /(rhs) = new_instance(@int / rhs.to_int) |
#<<(rhs) ⇒ Object
Shifts self left by rhs bits.
455 |
# File 'lib/bitint/base.rb', line 455 def <<(rhs) = new_instance(@int << rhs.to_int) |
#<=>(rhs) ⇒ Object
Compares self to rhs.
319 |
# File 'lib/bitint/base.rb', line 319 def <=>(rhs) = defined?(rhs.to_i) ? @int <=> (_ = rhs).to_i : nil |
#==(rhs) ⇒ Object
Checks to see if rhs is equal to selF
Example
U64 = BitInt::U(64)
twelve = U64.new(12)
# Behaves as you'd expect.
puts twelve == U64.new(12) #=> true
puts twelve == U64.new(13) #=> false
puts twelve == 12 #=> true
puts twelve == 12.0 #=> true
puts twelve == 13 #=> false
puts twelve == Object.new #=> false
281 282 283 |
# File 'lib/bitint/base.rb', line 281 def ==(rhs) defined?(rhs.to_i) && @int == rhs.to_i end |
#>>(rhs) ⇒ Object
Shifts self right by rhs bits.
460 |
# File 'lib/bitint/base.rb', line 460 def >>(rhs) = new_instance(@int >> rhs.to_int) |
#[] ⇒ Object
Gets the bit at index idx or returns nil.
This is equivalent to Integer#[]
482 |
# File 'lib/bitint/base.rb', line 482 def [](...) = __skip__ = @int.[](...) |
#^(rhs) ⇒ Object
Bitwise XORs self and rhs.
475 |
# File 'lib/bitint/base.rb', line 475 def ^(rhs) = new_instance(@int ^ rhs.to_int) |
#allbits?(mask) ⇒ Boolean
Returns true if all bits in ‘mask` are set in self.
492 |
# File 'lib/bitint/base.rb', line 492 def allbits?(mask) = @int.allbits?(mask) |
#anybits?(mask) ⇒ Boolean
Returns true if any bit in ‘mask` is set in self.
487 |
# File 'lib/bitint/base.rb', line 487 def anybits?(mask) = @int.anybits?(mask) |
#bin ⇒ Object
Returns a base-2 string of self. Equivalent to to_s(2).
Example
puts BitInt::U16.new(54321).bin #=> 0000010011010010
255 |
# File 'lib/bitint/base.rb', line 255 def bin = to_s(2) |
#bit_length ⇒ Object
Returns the amount of bits required to represent self
Unlike Integer#bit_length, this never changes and is equivalent to self.class::BITS.
505 |
# File 'lib/bitint/base.rb', line 505 def bit_length = self.class::BITS |
#byte_length ⇒ Object
Returns the amount of bytes required to represent self
This is equivalent to self.class::BYTES
512 |
# File 'lib/bitint/base.rb', line 512 def byte_length = self.class::BYTES |
#bytes(endian = :native) ⇒ Object
Returns all the bytes that’re used represent self
517 518 519 |
# File 'lib/bitint/base.rb', line 517 def bytes(endian = :native) each_byte(endian).to_a end |
#coerce(other) ⇒ Object
Converts other to an instance of self, and returns a tuple of [<converted>, self]
260 |
# File 'lib/bitint/base.rb', line 260 def coerce(other) = [new_instance(other.to_int), self] |
#downto(what) ⇒ Object
Same as Integer#downto, but returns instances of self.
401 402 403 404 405 406 407 408 409 |
# File 'lib/bitint/base.rb', line 401 def downto(what) return to_enum(_ = __method__) unless block_given? @int.downto what do |int| yield new_instance int end self end |
#each_byte(endian = :native) ⇒ Object
Executes the block once for each byte in self.
Bytes are converted to U8. If no block is given, returns an Enumerator
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 |
# File 'lib/bitint/base.rb', line 527 def each_byte(endian = :native) return to_enum(_ = __method__, endian) unless block_given? template = '_CS_L___Q'[self.class::BYTES] if template.nil? || template == '_' raise ArgumentError, 'bytes only works for sizes of 8, 16, 32, or 64.' end template.downcase! if self.class.signed? case endian when :native then # do nothing when :little then template.concat '<' unless self.class::BYTES == 1 when :big then template.concat '>' unless self.class::BYTES == 1 else raise ArgumentError, 'endian must be :big, :little, or :native' end [@int].pack(template).unpack('C*').each do |byte| #: Integer yield U8.new(byte) end self end |
#eql?(rhs) ⇒ Boolean
Checks to see if rhs is another BitInt::Base of the same class, and have the same contents.
289 290 291 |
# File 'lib/bitint/base.rb', line 289 def eql?(rhs) rhs.is_a?(self.class) && @int == rhs.to_i end |
#even? ⇒ Boolean
Checks to see if self is even.
376 |
# File 'lib/bitint/base.rb', line 376 def even? = @int.even? |
#hash ⇒ Object
Returns a hash code for this class.
296 |
# File 'lib/bitint/base.rb', line 296 def hash = [self.class, @int].hash |
#hex(upper: false) ⇒ Object
Returns a base-16 string of self. Equivalent to to_s(16).
If upper: true is passed, returns an upper-case version.
Examples
puts BitInt::U16.new(1234).hex #=> 04d2
puts BitInt::U16.new(1234, upper: true).hex #=> 04D2
239 |
# File 'lib/bitint/base.rb', line 239 def hex(upper: false) = to_s(16).tap { _1.upcase! if upper } |
#integer? ⇒ Boolean
Always return true, as BitInt::Bases are always integers.
301 |
# File 'lib/bitint/base.rb', line 301 def integer? = true |
#negative? ⇒ Boolean
Return whether self is a negative integer. Zero is not negative.
361 |
# File 'lib/bitint/base.rb', line 361 def negative? = @int.negative? |
#nobits?(mask) ⇒ Boolean
Returns true if no bits in ‘mask` are set in self.
497 |
# File 'lib/bitint/base.rb', line 497 def nobits?(mask) = @int.nobits?(mask) |
#nonzero? ⇒ Boolean
Returns a falsey value if zero, otherwise returns self.
371 |
# File 'lib/bitint/base.rb', line 371 def nonzero? = @int.nonzero? && self |
#oct ⇒ Object
Returns a base-8 string of self. Equivalent to to_s(8).
Example
puts BitInt::U16.new(12345).oct #=> 30071
247 |
# File 'lib/bitint/base.rb', line 247 def oct = to_s(8) |
#odd? ⇒ Boolean
Checks to see if self is odd.
381 |
# File 'lib/bitint/base.rb', line 381 def odd? = @int.odd? |
#positive? ⇒ Boolean
Returns whether self is a positive integer. Zero is not positive.
356 |
# File 'lib/bitint/base.rb', line 356 def positive? = @int.positive? |
#pred ⇒ Object
Gets the next value, or throws a OverFlowError if at the top.
436 437 438 439 |
# File 'lib/bitint/base.rb', line 436 def pred # TODO: this changes `@wrap`; that's weird new_instance(@int - 1, wrap: false) end |
#succ ⇒ Object
Gets the next value, or throws a OverFlowError if at the top.
428 429 430 431 |
# File 'lib/bitint/base.rb', line 428 def succ # TODO: this changes `@wrap`; that's weird new_instance(@int + 1, wrap: false) end |
#times ⇒ Object
Same as Integer#times, but returns instances of self.
387 388 389 390 391 392 393 394 395 |
# File 'lib/bitint/base.rb', line 387 def times return to_enum(_ = __method__) unless block_given? @int.times do |int| yield new_instance int end self end |
#to_f ⇒ Object
Converts self to a Float.
202 |
# File 'lib/bitint/base.rb', line 202 def to_f = @int.to_f |
#to_i ⇒ Object Also known as: to_int
Returns the underlying integer.
196 |
# File 'lib/bitint/base.rb', line 196 def to_i = @int |
#to_r ⇒ Object
Converts self to a Rational.
207 |
# File 'lib/bitint/base.rb', line 207 def to_r = @int.to_r |
#to_s(base = nil) ⇒ Object Also known as: inspect
Converts self to a String.
If no base is given, it just returns a normal String in base 10. If a base is given, a string padded with ‘0`s will be returned.
Examples
puts BitInt::U16.new(1234).to_s #=> 1234
puts BitInt::U16.new(1234).to_s(16) #=> 04d2
221 222 223 224 225 226 227 |
# File 'lib/bitint/base.rb', line 221 def to_s(base = nil) return @int.to_s unless base base = base.to_int adjusted = negative? ? (-2*self.class::MIN.to_i + @int).to_i : @int adjusted.to_s(base).rjust(self.class::BITS / Math.log2(base), negative? ? '1' : '0') end |
#upto(what) ⇒ Object
Same as Integer#downto, but returns instances of self.
415 416 417 418 419 420 421 422 423 |
# File 'lib/bitint/base.rb', line 415 def upto(what) return to_enum(_ = __method__) unless block_given? @int.upto what do |int| yield new_instance int end self end |
#zero? ⇒ Boolean
Returns whether self is zero.
366 |
# File 'lib/bitint/base.rb', line 366 def zero? = @int.zero? |
#|(rhs) ⇒ Object
Bitwise ORs self and rhs.
470 |
# File 'lib/bitint/base.rb', line 470 def |(rhs) = new_instance(@int | rhs.to_int) |
#~ ⇒ Object
Bitwise negates self.
450 |
# File 'lib/bitint/base.rb', line 450 def ~ = new_instance(~@int) |