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


556
557
558
559
560
# File 'lib/bitlab.rb', line 556

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.



541
542
543
# File 'lib/bitlab.rb', line 541

def length
  @length
end

#valueObject

Returns the value of attribute value.



541
542
543
# File 'lib/bitlab.rb', line 541

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


574
575
576
577
# File 'lib/bitlab.rb', line 574

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


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

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.



712
713
714
# File 'lib/bitlab.rb', line 712

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


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

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


666
667
668
669
# File 'lib/bitlab.rb', line 666

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.



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

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)


673
674
675
# File 'lib/bitlab.rb', line 673

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


687
688
689
690
691
# File 'lib/bitlab.rb', line 687

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.



718
719
720
721
722
723
724
# File 'lib/bitlab.rb', line 718

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


650
651
652
653
654
655
656
# File 'lib/bitlab.rb', line 650

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