#[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)
}
}
}
}