// Copyright (C) 2010 by Yan Huang package YaoGC; import java.math.*; public class State { public static class StaticWire { public int value = Wire.UNKNOWN_SIG; public BigInteger lbl = null; public boolean invd = false; StaticWire() { } public StaticWire(int v) { value = v; } public StaticWire(BigInteger label) { lbl = label; } } public StaticWire wires[]; public BigInteger plainValue = null; // The non-negative integer the state // object represents. public State(StaticWire[] ws) { wires = ws; for (int i = 0; i < ws.length; i++) { if (ws[i].value == Wire.UNKNOWN_SIG) { plainValue = null; return; } } plainValue = BigInteger.ZERO; for (int i = 0; i < ws.length; i++) { if (ws[i].value == 1) plainValue = plainValue.setBit(i); } } public State(BigInteger v, int length) { wires = new StaticWire[length]; for (int i = 0; i < length; i++) { wires[i] = new StaticWire(); wires[i].value = v.testBit(i) ? 1 : 0; } plainValue = v; } private State(int length) { wires = new StaticWire[length]; plainValue = null; } public static State flattenStateArray(State[] as) { State res = new State(as.length * as[0].wires.length); for (int i = 0; i < as.length; i++) for (int j = 0; j < as[0].wires.length; j++) { res.wires[i * 8 + j] = new StaticWire(); res.wires[i * 8 + j].value = as[i].wires[j].value; res.wires[i * 8 + j].lbl = as[i].wires[j].lbl; res.wires[i * 8 + j].invd = as[i].wires[j].invd; } return res; } public static State extractState(State s, int start, int end) { State res = new State(end - start); for (int i = 0; i < end - start; i++) { res.wires[i] = new StaticWire(); res.wires[i].value = s.wires[i + start].value; res.wires[i].lbl = s.wires[i + start].lbl; res.wires[i].invd = s.wires[i + start].invd; } return res; } public static State fromWires(Wire[] ws) { State.StaticWire[] swires = new State.StaticWire[ws.length]; for (int i = 0; i < ws.length; i++) { swires[i] = new StaticWire(); swires[i].value = ws[i].value; swires[i].lbl = ws[i].lbl; swires[i].invd = ws[i].invd; } return new State(swires); } public static State fromLabels(BigInteger[] lbs) { State res = new State(lbs.length); for (int i = 0; i < lbs.length; i++) res.wires[i] = new StaticWire(lbs[i]); return res; } public int getWidth() { return wires.length; } /* * Return "true" ONLY IF it is CERTAIN that the value denoted by "this" * object is larger than that denoted by "s". Namely, if "false" is * returned, it is still possible that ("this" > "s"). */ public boolean largerThan(State s) { if (plainValue != null && s.plainValue != null) return plainValue.compareTo(s.plainValue) > 0; return false; // this line should never be reached. } public static State signExtend(State s, int width) { if (s.getWidth() > width) { (new Exception("s is already wider than width.")).printStackTrace(); System.exit(1); } else if (s.getWidth() == width) return s; State res = new State(width); for (int i = 0; i < width; i++) if (i < s.wires.length) res.wires[i] = s.wires[i]; else res.wires[i] = s.wires[s.wires.length - 1]; res.plainValue = s.plainValue; return res; } public static State concatenate(State s1, State s2) { int width = s1.getWidth() + s2.getWidth(); State res = new State(width); for (int i = 0; i < width; i++) if (i < s2.wires.length) res.wires[i] = s2.wires[i]; else res.wires[i] = s1.wires[i - s2.wires.length]; if (s1.plainValue == null || s2.plainValue == null) res.plainValue = null; else res.plainValue = s1.plainValue.shiftLeft(s2.getWidth()).xor( s2.plainValue); return res; } public BigInteger[] toLabels() { BigInteger[] res = new BigInteger[getWidth()]; for (int i = 0; i < res.length; i++) res[i] = wires[i].lbl; return res; } }