Class: RubyLabs::BitLab::Code

Inherits:
Object
  • Object
show all
Defined in:
lib/bitlab.rb

Overview

Code

Code objects are variable-length binary numbers representing integers, letters, or members of a set.

In the projects described in the text readers do not create Code objects directly – instead Codes are created by methods in other classes, e.g. the code method added to the Fixnum class or the top level encode method defined in the BitLab module.

See also HexCode, a derived class that has the same operations and attributes but displays values with hexadecimal (base 16) digits.

#– Way cool – this class used to have a maxcodesize (set to 60) to make sure codes fit within a single 64-bit word. But a typo during one experiment created an 80-bit code. Turns out indexing etc work just fine on Bignums:

>> c1 = s.code(80)

> 00000000000000000000000000000000000000000000000000000000000000000000000001101000

>> c1.flip(0)

> 10000000000000000000000000000000000000000000000000000000000000000000000001101000

Direct Known Subclasses

HexCode

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(x, length = log2(x+1).ceil) ⇒ Code

Create a new code for the number x. An optional argument specifies the number of bits in the code, in which case the code will be padded with leading 0s (if the value is small enough to fit in that number of bits) or truncated (if the number is too big to fit in that number of bits).

Examples:

>> Code.new(26)
=> 11010
>> Code.new(26, 8)
=> 00011010
>> Code.new(26,4)
=> 1010


554
555
556
557
558
# File 'lib/bitlab.rb', line 554

def initialize(x, length = log2(x+1).ceil)
  @value = x % (1 << length)
  @length = length
  @has_parity_bit = false
end

Instance Attribute Details

#lengthObject

Returns the value of attribute length.



539
540
541
# File 'lib/bitlab.rb', line 539

def length
  @length
end

#valueObject

Returns the value of attribute value.



539
540
541
# File 'lib/bitlab.rb', line 539

def value
  @value
end

Instance Method Details

#+(bit) ⇒ Object

Create a new code by copying this code and extending it by one bit. The extra bit is appended on the right. The argument on the right side of the + operator should be an integer; the bit appended to the code is the least significant bit of this number.

Examples:

>> x = Code.new(4)
=> 100
>> x + 0
=> 1000
>> x + 1
=> 1001


572
573
574
575
# File 'lib/bitlab.rb', line 572

def +(bit)
  val = (@value << 1) | bit[0]
  return Code.new(val, @length+1)
end

#<<(x) ⇒ Object

Extend this code by attaching bits in x to the end of this code. The argument x can either be an integer, in which case one bit, corresponding to the least significant bit of x, is added to the end of the this code, or another Code object, in which case all the bits in x are added to the end of the this code.

Examples:

>> x = Code.new(4)
=> 100
>> y = Code.new(5)
=> 101
>> x << 1
=> 1001
>> x << y
=> 1001101


592
593
594
595
596
597
598
599
600
601
602
603
604
# File 'lib/bitlab.rb', line 592

def <<(x)
  if x.class == Code
    val = x.value     # val known to fit in x.length bits
    n = x.length
  else
    val = x[0]        # val is a single bit
    n = 1
  end
  @value <<= n
  @value |= val       # val can't have any higher order bits set -- see above
  @length += n
  return self
end

#<=>(x) ⇒ Object

Compare the numeric values of this object and Code object x.



710
711
712
# File 'lib/bitlab.rb', line 710

def <=>(x)
  return x.class == Code && @value <=> x.value
end

#[](i) ⇒ Object

Return one or more bits from this code. If the argument passed to this method is an integer, the method returns a single integer, either 0 or 1. If the argument is a Range, the method returns a new Code object with the specified bits from this code.

Note: The index operator for Fixnums orders bits from right to left, consistent with standard usage but the opposite of Strings and Arrays. In this module bits are ordered from left to right to be consistent with Strings and Arrays.

Example:

>> x = Code.new(117)
=> 1110101
>> x[1]
=> 1
>> x[1..3]
=> 110


624
625
626
627
628
629
630
631
632
633
# File 'lib/bitlab.rb', line 624

def [](i)
  if i.class == Range
    res = 0
    n = 0
    i.each { |j| res <<= 1; res |= @value[@length-j-1]; n += 1 }
    return Code.new(res, n)
  else
    return @value[@length-i-1]
  end
end

#add_parity_bitObject

Extend this code by adding a new bit, chosen so that this code will now have even parity.

Example:

>> x = Code.new(17)
=> 10001
>> x.add_parity_bit
=> 100010


664
665
666
667
# File 'lib/bitlab.rb', line 664

def add_parity_bit
  @has_parity_bit = true
  return self << parity_bit
end

#chrObject

Return a one-letter string containing the character encoded by this Code object, which must have fewer than 8 bits. Ignores the parity bit if it has been attached.



695
696
697
698
699
700
701
702
703
704
705
706
# File 'lib/bitlab.rb', line 695

def chr
  raise "code must have fewer than 8 bits" unless @value < 256
  if @has_parity_bit
    if even_parity?
      return (@value >> 1).chr
    else
      return "?"
    end
  else 
    return @value.chr
  end
end

#even_parity?Boolean

Return true or false, depending on whether this code has an even or odd number of 1 bits.

Returns:

  • (Boolean)


671
672
673
# File 'lib/bitlab.rb', line 671

def even_parity?
  return parity_bit() == 0
end

#flip(i) ⇒ Object

Invert bit i of this code object, where bit 0 is the leftmost bit (see the note about bit order in the documentation for the [] operator for Code objects).

Example:

>> x = Code.new(17)
=> 10001
>> x.flip(3)
=> 10011


685
686
687
688
689
# File 'lib/bitlab.rb', line 685

def flip(i)
  raise "bit index out of range" unless i < @length
  @value ^= (1 << (@length - i - 1))
  return self
end

#inspectObject Also known as: to_s

Return a string with the binary digits of the value represented by this Code object.



716
717
718
719
720
721
722
# File 'lib/bitlab.rb', line 716

def inspect
  if @length == 0
    return ""
  else
    return sprintf "%0#{@length}b", @value
  end
end

#parity_bitObject

Return the bit value that would give this code an even parity, i.e. if this code already has an even number of 1s return 0, if it has an odd number of 1s return 1.

Example:

>> x = Code.new(17)
=> 10001
>> x.parity_bit
=> 0
>> x << 1
=> 100011
>> x.parity_bit
=> 1


648
649
650
651
652
653
654
# File 'lib/bitlab.rb', line 648

def parity_bit
  bit = 0
  for i in 0...@length
    bit ^= @value[i]
  end
  return bit
end