{"id":22763576,"url":"https://github.com/mearns/rodlogic","last_synced_at":"2025-07-25T02:06:15.486Z","repository":{"id":44073426,"uuid":"207942976","full_name":"mearns/rodlogic","owner":"mearns","description":null,"archived":false,"fork":false,"pushed_at":"2022-12-30T18:38:31.000Z","size":189,"stargazers_count":0,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-30T09:42:10.269Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mearns.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-12T01:58:43.000Z","updated_at":"2020-10-23T19:41:39.000Z","dependencies_parsed_at":"2023-01-31T13:16:00.306Z","dependency_job_id":null,"html_url":"https://github.com/mearns/rodlogic","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mearns/rodlogic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mearns%2Frodlogic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mearns%2Frodlogic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mearns%2Frodlogic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mearns%2Frodlogic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mearns","download_url":"https://codeload.github.com/mearns/rodlogic/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mearns%2Frodlogic/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262720641,"owners_count":23353450,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-11T11:09:07.846Z","updated_at":"2025-06-30T06:07:32.783Z","avatar_url":"https://github.com/mearns.png","language":"JavaScript","readme":"# Rod Logic\n\n## Setup\n\nWe define the X axis as running from west (negative) to east (positive); the Y axis runs from south\n(negative) to north (positive); the Z axis runs from down (negative) to up (positive);\n\nConsider a set of rectangular prism \"rods\", each N units long, 2 units wide, and 1 unit high.\n\nRods are always oriented orthagonal to the axes with its height (1 unit) lying along the Z axis.\nRods can be oriented _horizontally_, such that its length (N units) lies along the X axis and its\nwidth (2 units) along the Y axis; or _vertically_, such that its length lies along the Y axis and its\nwith along the X axis.\n\nA rods location is described by the coordinate of it's most southwest down-most corner: rods are always located\non the lattice, i.e., the coordinates of its location are always integer unit values.\n\nFrom it's initial location, a rod is contrained to a single alternate location, which is translated\nby one unit in the positive direction of its length: horizontally oriented rods can be at their initial\nlocation (X, Y, Z), or at location (X+1, Y, Z); vertically oriented rods can be at their initial location\nor at location (X, Y+1, Z).\n\nRods in their initial location always have their width (2 units) coincident with an axis: horizontally\noriented rods have locations with an X coordinate of 0 (or 1 in the alternate location); vertically\noriented rods have locations with a Y coordinate of 0 (or 1 in the alternate location).\n\nA rod in it's initial location is considered to have a value of 0; a rod in it's alternate (translated)\nlocation is considered to have a value of 1.\n\nRods only exist in every other Z plane. In other words, the location of every rod has a Z value which is\neven (equivalent to 0 under modulo 2). Further more, horiztonally oriented rods only have locations with\nZ coordinates that are equivalent to 0 under modulo 4 (Z in { 0, 4, 8, etc. }), and vertically oriented rods\nonly have locations with Z coordinates that are equivalent to 2 under modulo 4 (Z in { 2, 6, 10, etc. }).\n\nSimilarly, a one-unit gap is left between adjacent rods. Horizontally aligned rods always have a location\nwith a Y value that is equivalent to 1 under modulo 3 (recall that they have a width of 2); vertically oriented\nrods always have a location with an X value equivalent to 1 under modulo 3.\n\nPutting it together:\n\n-   **horizontally oriented rods in their initial location** have locations `(0, 1 + 3j, 4k)`\n-   **horizontally oriented rods in their alternate location** have locations `(1, 1 + 3j, 4k)`\n-   **vertically oriented rods in their initial location** have locations `(1 + 3j, 0, 2 + 4k)`\n-   **vertically oriented rods in their alternate location** have locations `(1 + 3j, 1, 2 + 4k)`\n\nEach rod is uniquely identified by the three tuple of: `[orientation, j, k]`, where orientation is 0 for horizontally\noriented rods and 1 for vertically oriented rods, k is a non-negative integer indicating the \"layer pair\" of the rod,\nand j is a non-negative integer indicating it's index within its layer (each layer pair consists of two layers: one\nlayer of horizontally aligned rods, and one layer of vertically aligned rods, ad a one-unit high gap between the two layers).\n\nFor clarity, we will replace the two tuple of `[orientation, k]` with a single scalar value of `s`, where `s` is a non-negative\ninteger, and is equivalent to `[s % 2, k = floor(s / 2)]`, where `floor(x)` is the largest integer not greater than `x`. With this\nmodification, each rod is uniquely identified by the two-tuple `{j, s}`.\n\nEvery rod is partitioned into unit length _segments_ along its length. Segments are numbered sequentially starting at\n0 in the most south/west segment. E.g., a horizontally oriented rod in its initial location has segment 0 running from\nX=0 (its west-mode edge) to X=1, segment 1 from X=1 to X=2, etc. Positions belong to the rod, so they translate along\nwith the rod in it's alternate position.\n\nEvery rod has a _block_ installed at segments with numbers equivalent to 1 under modulo 3. Each _block_ is a solid\npiece one unit long, two units wide, and one unit high. The blocks are oriented with the rod they are installed on,\nso the blocks of a horizontally oriented rod are one unit in each of the X and Z dimensions (\"length\" and \"height\"),\nand two units in the Y dimension (\"width\").\n\nBlocks are located one unit _up_ from the rod they are installed on. Thus:\n\n-   blocks on a horizontally oriented rod at (x, y, z) have location `(x + 1 + 3i, y, z + 1)`\n-   blocks on a vertically oriented rod at (x, y, z) have location `(x, y + 1 + 3i, z + 1)`\n\nWhere `i` is a non-negative integer and `1 + 3i` is a position on the rod. Every rod has all possible blocks installed\non it, according to these rules.\n\nA block is unambiguously described by the rod its on, `{j, s}`, and the values of `i` (the index of the block along\nthe rod): `{j, s, i}`\n\nRods have optional _gates_ installed as well. Each gate is a cube 1 unit high, 1 unit wide, and 1 unit long. Gates\nare installed on rods at positions with numbers that are equivalent to 0 under modulo 3. Each such position can have\nup to 2 gates installed, at offsets of 0 or 1 units along the width of the rod. Gates are installed one unit down\nfrom the location of the rod on which they are installed. Thus:\n\n-   Gates on a horizontally oriented rod at (x, y, z) have location `(x + 3i, y + o, z - 1)`\n-   Gates on a vertically oriented rod at (x, y, z) have location `(x + o, y + 3i, z - 1)`\n\nWhere `i` is a non-negative integer, `3i` is a position on the rod, and `o` is either 0 or 1. Gates with an `o` value of\n0 are called _passing gates_, and gates with an o value of 1 are called _inverting gates_.\n\nA gate is unambiguously described by the rod its on, `{j, s}`, and the values of `i` (the index of the gate along\nthe rod) and `o` (which \"side\" of the rod it is on): `{j, s, i, o}`.\n\nBlocks and gates are considered solid, which means that they cannot overlap in space. Thus, a rod is not permitted to\nmove into it's alternate position if doing so would cause any blocks or gates to overlap.\n\n## Computation\n\nA set of rods, blocks, and gates as described above are considered to be a _computer_. The down-most layer of rods are\nconsidered to be the _input_ layer.\n\nTo _setup_ for computation, all rods are put in their initial positions. Then, the rods of the input layer are\npositioned to provide the input to the computation: The input rod at `{j, s=0}` is left in its initial location of\n`(0, 1 + 3j, 0)` to set a value of 0 for input-j; and put in it's alternate location of `(1, 1 + 3j, 0)` to set a value of 1\nfor input-j.\n\nTo perform the computation after _setup_ is complete, we step through subsequent each layer starting `s=1`; for each layer,\nwe push every rod in the layer that is allowed to be in it's alternate location into it's alternate location: rods that\nare not allowed to be in their alternate location are left in their initial location.\n\nOutput can be read from each layer as the sequence of equivalent values for each value based on it's resulting location: if\nrod j is left in its initial location, then output-j has a value of 0, other (it was able to be pushed to its alternate location),\noutput-j has a value of 1.\n\n## Understanding Computation\n\nEach rod \"intersects\" every rod on the adjacent layers (up and down) in exacly one spot, meaning they are both present\nin the same 2 unit by 2 unit square of the XY plane (but with different Z coordinates). Specifically, a horizontally\naligned rod `{j1, s1}` and vertically aligned rod `{j2, s2}` intersect in the 2 unit by 2 unit square with southwest\ncorner at `(1 + 3*j1, 1 + 3*j2)`.\n\nConsider rod `{j=0, s=0}` and\nrod `{j=0, s=1}`. In it's initial location, the \"down\" rod (s = 0), has a block at that is immediately adjacent to a gate\n`{0, 1, 0, 0}` on the \"up\" rod, in such a way that (if such a gate is present), prevents the \"up\" rod from being in its\nalternate location.\n\nOn the other hand, if the \"down\" rod is in its alternate location, then the down rod's block `{0, 0, 0}` is adjacent\nto a gate in the \"o=1\" position, at `{0, 1, 0, 1}`.\n\nMore generally, when rod `{j, s}` has in the initial location, the block at `{j, s, i}` will obstruct a gate (if present)\nat `{i, s + 1, j, 0}`; if the rod is in its alternate location, the block at `{j, s, i}` will obstruct a gate (if present)\nat `{i, s + 1, j, 1}`.\n\nBlocks are always present, but gates are selected to configure the computation. Individual gates are chosen to be obstructed\nby a block on the next rod down: a gate with `o=0` is obstructed when the down rod is in the initial state, and a gate with\n`o=1` is obstructed when the down rod is in the alternate state. A rod cannot move to its alternate position if any of its\ngates are obstructed. In this way, gates on a rod are configured to make that rod's output location (following computation\nas described above) a function of the locations of the rods below it.\n\nWe'll define `Cfg({j, s, i, o})` as 1 if the gate `{j, s, i, o}` is present, and 0 if it is not present, and `Val({j, s})`\nas 0 if the rod `{j, s}` is in its initial location and 1 if the rod is in its alternate location.\n\nConsider rod `{J, S}`, with `D` \"input\" rods in the next layer down: `{i, S - 1}` for `i` = 0, 1, 2, ..., D - 1.\nThe output value of the rod `{J, S + 1}` is defined as:\n\n$$\n\\product_{i = 0}^{i \u003c D}\n    (~Cfg({J, S, i, 0}))(~Cfg({J, S, i, 1}))\n    + (~Cfg({J, S, i, 0}))(Cfg({J, S, i, 1}))(~Val({i, S - 1}))\n    + (Cfg({J, S, i, 0}))(~Cfg({J, S, i, 1}))(Val({i, S - 1}))\n$$\n\nEach pair of gates on the \"up\" rod has an associated input rod on the next layer down. Specifically, the gates with\n`{J, S, I, o}`, for either value of `o`, are associated with \"input\" rod `{I, S - 1}`.\n\nWe can summarize this in a more intuitive way:\n\n-   If both gates are present on a segment, the rod will be obstructed regardless of the location of the\n    associated input rod, and the output rod will have a fixed value of 0.\n-   If neither gate is present on a segment, the rod will be _unobstructed_ regardless of the location\n    of the associated input rod.\n-   If the passing gate (o = 0) is present and the inverting gate (o = 1) is not, then the output rod\n    will be obstructed by the input rod if and only if the input rod is in the initial position (input\n    value of 0).\n-   If the inverting gate (o = 1) is present and the passing gate (o = 0) is not, then the output rod\n    will be obstructed by the input rod if and only if the input rod is in the alternate position (input\n    value of 1).\n\nThis is way the passing gate and inverting gates are called as such: as long as only one gate is present, the\npassing gate being present permits the input rod to pass its value to the output rod, while the inverting\ngate being present permits the input rod the pass the inverse of of its value to the output rod.\n\nRecall, however, that the actual output of a rod is 0 if _any_ of its gates are obstructed, and 1 only if\nit has _no obstructed gates_.\n\nWe can further simplify the configuration of gates as follows:\n\n| Passing | Inverting || Output | Configuration |\n| ------- | --------- || ------ | ------------- |\n| 0 | 0 || 1 | \"DONT CARE\" |\n| 0 | 1 || ~d | \"INVERT\" |\n| 1 | 0 || d | \"PASS\" |\n| 1 | 1 || 0 | \"ZERO\" |\n\nThis table uses `d` as the value of the corresponding input, and a 1 to indicate that the gate is present,\n0 to indicate that it's absent.\n\n## Building Blocks\n\nEach gate-pair on a rod is a Boolean-valued function of the associated input value. The output value of a rod with\nits gates is the logical conjunction of each of its gate functions applied to the associated input.\n\nThe gate-pairs on a rod provide the following basic building blocks:\n\n### Don't Care: `[DC]`\n\nBy setting a gate-pair to the DONT CARE configuration, the output becomes independent of the associated input.\n\n### Positive `[P]`\n\nBy the setting a gate-pair to the PASS configuration, the output becomes positively dependent on the input: the output\ncannot be 1 unless the associated input is 1.\n\n### Negative `[I]`\n\nBy setting the gate-pair to the INVERT configuration, the output becomes negatively dependent on the input: the output\ncannot be a 1 unless the associated input is 0.\n\n### Zero `[Z]`\n\nBy setting any gate-pair to the ZERO configuration, the rod becomes unconditionally obstructed and the output will have\na value of 0 regardless of _any_ inputs.\n\n### And `[P, P, ...]`\n\nBy setting gate-pairs on two different inputs to the PASS configuration, the output becomes positively dependent on the\n_conjunction_ of the two associated inputs: the output cannot be 1 unless _both_ associated inputs are 1.\n\nThis can be extended from 2 inputs to any number of inputs.\n\n### Nor `[I, I, ...]`\n\nBy setting a gate-pairs on two or more inputs to the INVERT coniguration, the output becomes positively dependent on the\n_joint denial_ (\"NOR\") of the associated inputs: the output cannot be 1 unless _all_ associated inputs are 0.\n\nThis follows from DeMorgans law as the INVERT configuration for each input makes the output a conjunction including the\ninverse of that input, thus (~A)(~B), which is equivalent (by DeMorgan's law) to ~(~(A) + ~(~B)) or simply ~(A + B).\n\nAs has been shown elsewhere, all boolean functions can be synthesized from multiple layers of NOR gate, thus\nthe model is computationally complete.\n\n-   NOT(A) = NOR(A, 0)\n-   OR(A, B) = NOT(NOR(A, B))\n-   AND(A, B) = NOR(NOT(A), NOT(B))\n\n## Larger Circuits\n\nLarger logic circuits can be implemented by combining the building blocks above, on a single rod, across multiple rods,\nand across multiple layers.\n\n### 2x1 multiplexer\n\nA 2x1 multiplexer with inputs A and B and select S is defined as `(~SA) + (SB)`. This can be set up on three layers,\nusing 2 rods, 1 rod, and 1 rod, respectively.\n\n-   Layer 1:\n    -   Rod C: { S: I, A: P } = ~SA\n    -   Rod D: { S: P, B: P } = SB\n-   Layer 2:\n    -   Rod E: { C: I, D: I } = ~C~D = ~(C + D) = ~(~SA + SB)\n-   Layer 3:\n    -   Rod F: { E: I } = ~E = ~(~(~SA + SB)) = ~SA + SB\n\n### Data Register\n\nData from one rod can be passsed up through layers simply by creating a rod that has a PASS configuration in the associated\ngate-pair, and leaving the rest of the gates on the rod as DONT CARE.\n\nHowever, to serve as a mutable data register, you need a way of changing the value. There are a variety of ways to do this.\nOne way to uses the input data, D, a write value W, a write-enable value E, and the output data Q. The output Q is taken\nas the output of a 2x1 multiplexer which has D as its first input, W as its second input, and E as its select line. When\nthe E value is 0, Q gets the value of D, i.e., the register is unchanged. When E is 1, Q gets the value from W, i.e., the\nregister is set to the provided write value.\n\n-   Layer 1:\n    -   Rod F: { E: I, D: P }\n    -   Rod G: { E: P, W: P }\n-   Layer 2:\n    -   Rod H: { F: I, G: I }\n-   Layer 3:\n    -   Rod J: { H: I }\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmearns%2Frodlogic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmearns%2Frodlogic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmearns%2Frodlogic/lists"}