#[no_std] number_to_binary = (n: @number, bits: @number) { let digits = [] let n = n for i in bits..0 { x = 2^i if n >= x { n -= x digits.push(true) } else { digits.push(false) } } return digits.reverse() } type @binary_counter impl @binary_counter { new: (from: @number = 0, bits: @number = 16) { digits = number_to_binary(from, bits) let data = [] for i in ..bits { data.push(@counter::new(digits[i])) } carry = @counter::new(0) return @binary_counter::{ data, carry } }, _as_: (self, typ: @type_indicator) { if typ == @counter { c = @counter::new() for i in ..self.data.length { self.data[i].item.if_is(EQUAL_TO, 1, !{ c.add(2^i) }) } return c } else { throw "Binary counter cannot convert to type: " + @string(typ) } }, take: (self, source: @counter) { for i in self.data.length..0 { x = 2^i -> if source >= x { source -= x self.data[i] += 1 } } }, copy_to: (self, target: @counter | [@counter] | @binary_counter | [@binary_counter]) { for i in ..self.data.length { self.data[i].item.if_is(EQUAL_TO, 1, !{ if target.type == @array { for t in target { t.add(2^i) } } else { target.add(2^i) } }) } }, add_to: (self, target: @counter | [@counter]) { for i in ..self.data.length { self.data[i].item.if_is(EQUAL_TO, 1, !{ if target.type == @array { for t in target { t.add(2^i) } } else { target.add(2^i) } self.data[i] -= 1 }) } }, display: (self, x: @number, y: @number) { // reverse order to get highest order digit first for i in self.data.length..0 { self.data[i].display(x + 30 * (self.data.length-i), y) } }, add: (self, num: @number | @binary_counter) { if num.type == @number { bin = number_to_binary(num, self.data.length) for i in ..self.data.length { -> if bin[i] && counter() == 0 { self.data[i] += 1 } -> if self.carry == 1 { self.data[i] += 1 self.carry -= 1 } -> if self.data[i] > 1 { self.data[i] -= 2 self.carry += 1 } } } else if num.type == @binary_counter { for i in ..self.data.length { -> if num.data[i] == 1 { self.data[i] += 1 } -> if self.carry == 1 { self.data[i] += 1 self.carry -= 1 } -> if self.data[i] > 1 { self.data[i] -= 2 self.carry += 1 } } } /* -> if self.carry == 1 { self.carry -= 1 } */ }, assign: (self, num: @number | @binary_counter) { let bin = [] if num.type == @number { bin = number_to_binary(num, self.data.length) } else if num.type == @binary_counter { bin = num.data } for i in ..self.data.length { -> if self.data[i] == 1 { -> if bin[i] == 0 { self.data[i] -= 1 } } -> if self.data[i] == 0 { -> if bin[i] == 1 { self.data[i] += 1 } } } }, reset: (self) { for d in self.data { -> if d == 1 { d -= 1 } } }, compare: (self, other: @binary_counter) { for i in self.data.length..0 { if self.data[i] == 1 && other.data[i] == 0 { return 1 } else if self.data[i] == 0 && other.data[i] == 1 { return -1 } } return 0 }, shift: (self, n: @number) { move = (i) { -> if self.data[i] == 1 { self.data[i + n] += 1 self.data[i] -= 1 } } if n > 0 { for i in (self.data.length - n)..self.data.length { -> if self.data[i] == 1 { self.data[i] -= 1 } } for i in (self.data.length - n)..-1 { move(i) } } else if n < 0 { for i in ..(-n) { -> if self.data[i] == 1 { self.data[i] -= 1 } } for i in (-n)..self.data.length { move(i) } } } }