LittleBigPlanet 2の論理回路 (3)

 「ORゲート→方向分割ツール」に特殊な挙動を観測したので、信号(Signal構造体)の定義を調整します。「Backward」を追加しました。信号Backwardは、通常、信号Aが負のときtrueとなります。

信号(Backward追加版)

    // 信号(デジタルとアナログを含む)
    struct Signal {
        // false(オフ), true(オン)。信号の表示上の明暗はこの値で決定される。Dがfalse(オフ/暗いとき)でも、Aが0とは限らない。
        public bool D;
        // 方向分割の出力決定に使う。通常はAが負のときtrue。特別な場合、Aの負号との関係が崩れる。
        public bool Backward;
        public int A; // -100 〜 +100 [%]

        // DがオフかつAが0%のことを「Signal.Zero」と呼ぶことにする。未接続の入力端子はこの状態。
        public static readonly Signal Zero = new Signal(false, 0);
        // DがオンかつAが100%のことを「Signal.One」と呼ぶことにする。
        public static readonly Signal One = new Signal(true, 100);

        public Signal(bool d, int a) {
            D = d;
            A = a;
            Backward = a < 0;
        }
        public Signal(bool d, int a, bool backward) {
            D = d;
            A = a;
            Backward = backward;
        }
        // 引数notがtrueのとき、出力Dは、入力Dの否定で、Aの符号は消える。
        // falseのとき、値は変化せず、Aの符号も保存される。
        public void InvertIf(bool not) {
            if (not) {
                D = !D;
		Backward = !Backward;
                A = 100 - Math.Abs(A);
            }
        }
    }

方向分割ツール

 入力Backwardに応じて、2つの出力端子の片方に出力されます。

    // 方向分割ツール
    // 入力Backwardに応じて、2つの出力の片方に信号を出力(falseのとき+側出力、trueのとき-側出力)する。
    // 出力Dは、選択された側のみがtrueとなる。選択された側の出力Aは、入力Aの絶対値となる。
    // 選択されていない側の出力は、Signal.Zeroとなる。
    public class DirectionSplitter : Logic {
        public void Update() {
            Outputs[0] = new Signal(!Inputs[0].Backward, Math.Max(0, Inputs[0].A));
            Outputs[1] = new Signal(Inputs[0].Backward, Math.Max(0, -Inputs[0].A));
        }
    }

ANDゲート

 2端子以上の入力から、1出力を得ます。

 デジタル回路としては、論理積として利用できます。出力Dは、すべての入力がONのときのみ、ONになります。
 アナログ回路としては、最小値として利用できます。出力Aは、すべての入力の絶対値のうち最小の入力の絶対値に、入力の負号の数が奇数個のときのみ負号をつけた値になります。

    // ANDゲート: 出力Dは論理積として機能する。
    // 出力Aは、絶対値が最小の入力Aを選び、その符号は、各入力Aに対して符号関数を適用した結果の積(負号が奇数個のとき負)となる。
    // 出力Backwardは通常通り(符号関数を結果の積が負のときtrueとなる)。
    public class AndGate : Logic {
        public bool Inverse;
        public AndGate() : base(2, 1) { }
        public void Update() {
            var d = true;
            var a = 100;
            var s = 1;
            foreach (var input in Inputs) {
                d &= input.D;
                a = Math.Min(a, Math.Abs(input.A));
                s *= Math.Sign(input.A);
            }
            var result = new Signal(d, s * a);
            result.InvertIf(Inverse);
        }
    }

ORゲート

 2端子以上の入力から、1出力を得ます。

 デジタル回路としては、論理和として利用できます。出力Dは、1つでも入力がONであれば、ONになります。
 アナログ回路としては、最小値として利用できます。出力Aは、すべての入力のうち絶対値が最大の入力(同値は若い入力端子が優先)のもとの入力値(符号付き)になります。出力Backwardは、入力0(最も上方の端子)Backwardになります。

    // ORゲート: Dは論理和として機能する。
    // 出力Aは、絶対値が最大の入力Aを選び(同値は若い入力端子が優先)、その入力Aのもとの値(符号付き)となる。
    // 出力Backwardは、入力0(最も上方の端子)Backwardとなる。
    public class OrGate : Logic {
        public bool Inverse;
        public OrGate() : base(2, 1) { }
        public void Update() {
            var d = false;
            var a = 0;
            foreach (var input in Inputs) {
                d |= input.D;
                if (Math.Abs(input.A) > Math.Abs(a)) a = input.A;
            }
            var result = new Signal(d, a, Inputs[0].Backward);
            result.InvertIf(Inverse);
        }
    }

 実験した限り、ORゲートの出力Backwardは特殊で、出力Aの符号とは一致しない結果が現れることがありました。DとAでは表せない情報があるとして、「Signal.Backward」を追加しました。