---
title: "full adder (and n-bit adder!)"
author:
- name: "Declan Naughton 🧮👨💻🧉"
url: "https://calcwithdec.dev/about.html"
description: "some modelling with circuit gates in calculang"
#execute:
# echo: false # set to false for publish
#code-tools: true
format:
html:
#page-layout: full
##page-layout: custom
resources:
- "../../models/adders/*"
# specs?
code-fold: true
embed-resources: false # faster with true, I think
---
The full adder below adds 3 binary inputs (`A_in`, `B_in`, `C_in`) and produces 2 binary outputs: `sum` and `carry`. It is made using modular [calculang](https://github.com/calculang/calculang).
Multiple adders can be combined to perform more complicated addition.
The logical components are the same logical components that combine to produce a CPU and a computer.
::: {.callout-tip title="Whacky idea 🤯" collapse="true"}
Is it possible to simulate a computer in calculang? Would it be useful? Would it be hard? (tbc)
Computers have been simulated in [whackier ways](https://www.youtube.com/watch?v=CW9N6kGbu2I&t=2s).
:::
## model output
```{ojs}
vega_interactive(viz)
viz = calcuvizspec({
models: [full],
input_cursors: [{}],
mark: 'text',
encodings: {
x: {'name': 'A_in', type:'nominal', domain: [0,1]},
y: {'name': 'B_in', type:'nominal', domain: [0,1]},
column: {'name': 'C_in', domain: [0,1]},
text: {'name': 'value', type:'quantitative'},
row: {'name': 'formula', domain: ['sum','carry']},
color: {'name': 'value', type:'nominal'}
},
width: 100, height:100,
spec_post_process: spec => { spec.config = {legend: { disable: true}}; return spec}
})
DOM.download(serialize(viz.datasets.data), "data", "csv download") // pivot/unpivot?
```
## calculang source
[on GitLab](https://gitlab.com/declann/calcy-quarty-vizy-template/-/tree/main/models/adders)
```{.js filename="full-adder.cul.js"}
import { XOR, AND, OR } from "./gates.cul.js";
export const A = () => A_in;
export const B = () => B_in;
export const C = () => C_in; // carry in
export const sum = () => XOR({ A_in: XOR(), B_in: C() });
export const carry = () =>
OR({ A_in: AND(), B_in: AND({ A_in: XOR(), B_in: C() }) });
```
```{.js filename="gates.cul.js" collapse="true"}
// soon: rewrite on NAND logic
export const A = () => A_in;
export const B = () => B_in;
export const AND = () => A() && B();
export const NAND = () => !AND(); // not and
export const OR = () => A() || B();
export const XOR = () => {
// exclusive or
if (AND()) return 0;
else return OR();
};
```
# n-bit adder
I need to do some bit re-ordering stuff and split into a separate notebook.
```{ojs}
viewof A_string_in = Inputs.text({value: "000"})
viewof B_string_in = Inputs.text({value: "111"})
vega_interactive(
calcuvizspec({
models: [n_bit_adder],
input_cursors: [{A_string_in, B_string_in}],
mark: 'text',
encodings: {
//x: {'name': 'A_in', type:'nominal', domain: [0,1]},
//y: {'name': 'B_in', type:'nominal', domain: [0,1]},
x: {'name': 'bit_in', domain: _.range(0,A_string_in.length,1)},
text: {'name': 'value', type:'quantitative'},
y: {'name': 'formula', domain: ['sum','carry','A_bit','B_bit']},
color: {'name': 'value', type:'nominal'}
},
width: 100, height:100,
spec_post_process: spec => { spec.config = {legend: { disable: true}}; return spec}
}))
```
## appendix
```{ojs}
import {calcuvizspec} from "@declann/little-calcu-helpers"
//import { aq, op } from '@uwdata/arquero'
vega_interactive = { // credit to Mike Bostock (starting point): https://observablehq.com/@mbostock/hello-vega-embed
const v = window.vega = await require("vega");
const vl = window.vl = await require("vega-lite");
const ve = await require("vega-embed");
async function vega(spec, options) {
const div = document.createElement("div");
div.setAttribute('id','chart-out');
div.value = (await ve(div, spec, options)).view;
div.value.addEventListener('mousemove', (event, item) => {
//console.log(item);
if (item != undefined && item.datum != undefined && item.datum.formula != undefined) {
/*DN off viewof formula_select.value = item.datum.formula;
viewof formula_select.dispatchEvent(new CustomEvent("input"))
*/
}
})
div.value.addEventListener('click', (event, item) => {
console.log(item.datum);
}) // DN
return div;
}
vega.changeset = v.changeset;
return vega;
} //
```
```{ojs}
full = require('../../models/adders/full-adder.js');
n_bit_adder = require('../../models/adders/n-bit-adder.js');
full
n_bit_adder
```
```{ojs}
json2csv = require("json2csv@5.0.7/dist/json2csv.umd.js")
// thx to https://observablehq.com/@palewire/saving-csv
// Ben Welsh and comments from Christophe Yamahata
function serialize (data) {
let parser = new json2csv.Parser();
let csv = parser.parse(data);
return new Blob([csv], {type: "text/csv"})
}
function serializeJSON (data) {
return new Blob([JSON.stringify(data,null,2)], {type: "text/json"})
}
```