48 lines
1.3 KiB
Plaintext
48 lines
1.3 KiB
Plaintext
defmodule RC do
|
|
use Bitwise
|
|
@bit_size 4
|
|
|
|
def four_bit_adder(a, b) do # returns pair {sum, carry}
|
|
a_bits = binary_string_to_bits(a)
|
|
b_bits = binary_string_to_bits(b)
|
|
Enum.zip(a_bits, b_bits)
|
|
|> List.foldr({[], 0}, fn {a_bit, b_bit}, {acc, carry} ->
|
|
{s, c} = full_adder(a_bit, b_bit, carry)
|
|
{[s | acc], c}
|
|
end)
|
|
end
|
|
|
|
defp full_adder(a, b, c0) do
|
|
{s, c} = half_adder(c0, a)
|
|
{s, c1} = half_adder(s, b)
|
|
{s, bor(c, c1)} # returns pair {sum, carry}
|
|
end
|
|
|
|
defp half_adder(a, b) do
|
|
{bxor(a, b), band(a, b)} # returns pair {sum, carry}
|
|
end
|
|
|
|
def int_to_binary_string(n) do
|
|
Integer.to_string(n,2) |> String.rjust(@bit_size, ?0)
|
|
end
|
|
|
|
defp binary_string_to_bits(s) do
|
|
String.codepoints(s) |> Enum.map(fn bit -> String.to_integer(bit) end)
|
|
end
|
|
|
|
def task do
|
|
IO.puts " A B A B C S sum"
|
|
Enum.each(0..15, fn a ->
|
|
bin_a = int_to_binary_string(a)
|
|
Enum.each(0..15, fn b ->
|
|
bin_b = int_to_binary_string(b)
|
|
{sum, carry} = four_bit_adder(bin_a, bin_b)
|
|
:io.format "~2w + ~2w = ~s + ~s = ~w ~s = ~2w~n",
|
|
[a, b, bin_a, bin_b, carry, Enum.join(sum), Integer.undigits([carry | sum], 2)]
|
|
end)
|
|
end)
|
|
end
|
|
end
|
|
|
|
RC.task
|