From d74eb0a0ce6211e4d92dd3558beda89690af11ea Mon Sep 17 00:00:00 2001 From: hneemann Date: Fri, 3 Jun 2016 16:31:34 +0200 Subject: [PATCH] Added a LaTeX export to truth table --- .../expression/format/FormatToTableLatex.java | 11 +-- .../analyse/format/TruthTableFormatter.java | 20 ++++++ .../format/TruthTableFormatterLaTeX.java | 72 +++++++++++++++++++ ...inMapDialog.java => ShowStringDialog.java} | 13 ++-- .../gui/components/table/TableDialog.java | 47 ++++++++++-- src/main/resources/lang/lang_de.properties | 4 +- src/main/resources/lang/lang_en.properties | 2 + .../expression/format/FormatterTest.java | 6 +- .../format/TruthTableFormatterLaTeXTest.java | 32 +++++++++ 9 files changed, 185 insertions(+), 22 deletions(-) create mode 100644 src/main/java/de/neemann/digital/analyse/format/TruthTableFormatter.java create mode 100644 src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeX.java rename src/main/java/de/neemann/digital/gui/components/table/{ShowPinMapDialog.java => ShowStringDialog.java} (53%) create mode 100644 src/test/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeXTest.java diff --git a/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTableLatex.java b/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTableLatex.java index 14fbdae0e..92b32041d 100644 --- a/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTableLatex.java +++ b/src/main/java/de/neemann/digital/analyse/expression/format/FormatToTableLatex.java @@ -52,10 +52,11 @@ public class FormatToTableLatex extends FormatToTable { * @param identifier the identifier * @return the formatted text */ - protected static String formatIdentifier(String identifier) { - if (identifier.length() <= 1) - return identifier; - else - return identifier.charAt(0) + "_{" + identifier.substring(1) + "}"; + public static String formatIdentifier(String identifier) { + int p = identifier.indexOf("_"); + if (p < 0) return identifier; + + String index = identifier.substring(p + 1); + return identifier.substring(0, p + 1) + "{" + index + "}"; } } diff --git a/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatter.java b/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatter.java new file mode 100644 index 000000000..25897113a --- /dev/null +++ b/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatter.java @@ -0,0 +1,20 @@ +package de.neemann.digital.analyse.format; + +import de.neemann.digital.analyse.TruthTable; +import de.neemann.digital.analyse.expression.ExpressionException; + +/** + * Formats a truth table + * + * @author hneemann + */ +public interface TruthTableFormatter { + + /** + * Creates a string representation of the table + * + * @param truthTable the table + * @return the string representation + */ + String format(TruthTable truthTable) throws ExpressionException; +} diff --git a/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeX.java b/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeX.java new file mode 100644 index 000000000..f24dc6356 --- /dev/null +++ b/src/main/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeX.java @@ -0,0 +1,72 @@ +package de.neemann.digital.analyse.format; + +import de.neemann.digital.analyse.TruthTable; +import de.neemann.digital.analyse.expression.ContextFiller; +import de.neemann.digital.analyse.expression.ExpressionException; +import de.neemann.digital.analyse.expression.Variable; +import de.neemann.digital.analyse.expression.format.FormatToTableLatex; +import de.neemann.digital.analyse.quinemc.ThreeStateValue; + +/** + * @author hneemann + */ +public class TruthTableFormatterLaTeX implements TruthTableFormatter { + @Override + public String format(TruthTable truthTable) throws ExpressionException { + StringBuilder sb = new StringBuilder(); + sb.append("\\begin{center}\n\\begin{tabular}{"); + for (Variable v : truthTable.getVars()) + sb.append("c"); + sb.append("|"); + for (int i = 0; i < truthTable.getResultCount(); i++) + sb.append("c"); + sb.append("}\n"); + + for (Variable v : truthTable.getVars()) + sb.append("$").append(formatVar(v.getIdentifier())).append("$&"); + for (int i = 0; i < truthTable.getResultCount(); i++) { + sb.append("$").append(formatVar(truthTable.getResultName(i))).append("$"); + if (i < truthTable.getResultCount() - 1) + sb.append("&"); + } + sb.append("\\\\\n"); + sb.append("\\hline\n"); + + ContextFiller cf = new ContextFiller(truthTable.getVars()); + for (int i = 0; i < cf.getRowCount(); i++) { + cf.setContextTo(i); + for (Variable v : cf) + sb.append(format(cf.get(v))).append("&"); + + for (int j = 0; j < truthTable.getResultCount(); j++) { + ThreeStateValue r = truthTable.getResult(j).get(i); + sb.append(format(r)); + if (j < truthTable.getResultCount() - 1) + sb.append("&"); + } + sb.append("\\\\\n"); + } + sb.append("\\end{tabular}\n\\end{center}\n"); + return sb.toString(); + } + + private String format(boolean b) { + return format(ThreeStateValue.value(b)); + } + + private String format(ThreeStateValue r) { + switch (r) { + case one: + return "$1$"; + case zero: + return "$0$"; + case dontCare: + return "-"; + } + return null; + } + + public static String formatVar(String var) { + return FormatToTableLatex.formatIdentifier(var); + } +} diff --git a/src/main/java/de/neemann/digital/gui/components/table/ShowPinMapDialog.java b/src/main/java/de/neemann/digital/gui/components/table/ShowStringDialog.java similarity index 53% rename from src/main/java/de/neemann/digital/gui/components/table/ShowPinMapDialog.java rename to src/main/java/de/neemann/digital/gui/components/table/ShowStringDialog.java index 6dd0ee751..dbce22a2e 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/ShowPinMapDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/ShowStringDialog.java @@ -1,7 +1,6 @@ package de.neemann.digital.gui.components.table; import de.neemann.digital.builder.PinMap; -import de.neemann.digital.lang.Lang; import javax.swing.*; @@ -10,18 +9,18 @@ import javax.swing.*; * * @author hneemann */ -public class ShowPinMapDialog extends JDialog { +public class ShowStringDialog extends JDialog { /** * Creates a new instance * - * @param parent the parent - * @param pinMapping the pin map to show + * @param parent the parent + * @param str the pin map to show */ - public ShowPinMapDialog(JFrame parent, PinMap pinMapping) { - super(parent, Lang.get("win_pinMapDialog")); + public ShowStringDialog(JFrame parent, String title, String str) { + super(parent, title); - JTextArea text = new JTextArea(pinMapping.toString()); + JTextArea text = new JTextArea(str); text.setEditable(false); getContentPane().add(new JScrollPane(text)); diff --git a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java index 7cba42ce0..609764fee 100644 --- a/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/table/TableDialog.java @@ -6,11 +6,13 @@ import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.ExpressionException; import de.neemann.digital.analyse.expression.Variable; import de.neemann.digital.analyse.expression.format.FormatToExpression; +import de.neemann.digital.analyse.expression.format.FormatToTableLatex; import de.neemann.digital.analyse.expression.format.FormatterException; import de.neemann.digital.analyse.expression.modify.ExpressionModifier; import de.neemann.digital.analyse.expression.modify.NAnd; import de.neemann.digital.analyse.expression.modify.NOr; import de.neemann.digital.analyse.expression.modify.TwoInputs; +import de.neemann.digital.analyse.format.TruthTableFormatterLaTeX; import de.neemann.digital.analyse.quinemc.BoolTableIntArray; import de.neemann.digital.builder.*; import de.neemann.digital.builder.Gal16v8.Gal16v8CuplExporter; @@ -116,6 +118,23 @@ public class TableDialog extends JDialog { JMenuBar bar = new JMenuBar(); + JMenu fileMenu = new JMenu(Lang.get("menu_file")); + + fileMenu.add(new ToolTipAction(Lang.get("menu_table_exportTableLaTeX")) { + @Override + public void actionPerformed(ActionEvent e) { + try { + String text = new TruthTableFormatterLaTeX().format(model.getTable()); + text += getExpressionsLaTeX(); + new ShowStringDialog(parent, Lang.get("win_table_exportDialog"), text).setVisible(true); + } catch (ExpressionException | FormatterException e1) { + new ErrorMessage(Lang.get("msg_errorDuringCalculation")).addCause(e1).show(); + } + } + }); + + bar.add(fileMenu); + JMenu sizeMenu = new JMenu(Lang.get("menu_table_new")); JMenu combinatorial = new JMenu(Lang.get("menu_table_new_combinatorial")); @@ -257,7 +276,7 @@ public class TableDialog extends JDialog { public void actionPerformed(ActionEvent actionEvent) { Gal16v8JEDECExporter jedecExporter = new Gal16v8JEDECExporter(); createHardware(jedecExporter, filename); - new ShowPinMapDialog(parent, jedecExporter.getPinMapping()).setVisible(true); + new ShowStringDialog(parent, Lang.get("win_pinMapDialog"), jedecExporter.getPinMapping().toString()).setVisible(true); } }.setToolTip(Lang.get("menu_table_create_gal16v8_tt")).createJMenuItem()); @@ -286,7 +305,7 @@ public class TableDialog extends JDialog { try { try (OutputStream out = new FileOutputStream(fileChooser.getSelectedFile())) { expressionExporter.getPinMapping().addAll(pinMap); - new BuiderExpressionCreator(expressionExporter.getBuilder(), ExpressionModifier.IDENTITY).create(); + new BuilderExpressionCreator(expressionExporter.getBuilder(), ExpressionModifier.IDENTITY).create(); expressionExporter.writeTo(out); } } catch (ExpressionException | FormatterException | IOException | FuseMapFillerException | PinMapException e) { @@ -298,7 +317,7 @@ public class TableDialog extends JDialog { private void createCircuit(ExpressionModifier... modifier) { try { CircuitBuilder circuitBuilder = new CircuitBuilder(shapeFactory); - new BuiderExpressionCreator(circuitBuilder, modifier).create(); + new BuilderExpressionCreator(circuitBuilder, modifier).create(); Circuit circuit = circuitBuilder.createCircuit(); SwingUtilities.invokeLater(() -> new Main(null, circuit).setVisible(true)); } catch (ExpressionException | FormatterException | RuntimeException e) { @@ -328,7 +347,7 @@ public class TableDialog extends JDialog { Gal16v8CuplExporter cupl = new Gal16v8CuplExporter(name.substring(0, name.length() - 4)); cupl.getPinMapping().addAll(pinMap); - new BuiderExpressionCreator(cupl.getBuilder(), ExpressionModifier.IDENTITY).create(); + new BuilderExpressionCreator(cupl.getBuilder(), ExpressionModifier.IDENTITY).create(); try (FileOutputStream out = new FileOutputStream(f)) { cupl.writeTo(out); } @@ -408,6 +427,22 @@ public class TableDialog extends JDialog { } } + private String getExpressionsLaTeX() throws ExpressionException, FormatterException { + StringBuilder sb = new StringBuilder(); + new ExpressionCreator(model.getTable()) { + @Override + public void resultFound(String name, Expression expression) throws FormatterException { + sb + .append(FormatToTableLatex.formatIdentifier(name)) + .append("=") + .append(FormatToExpression.FORMATTER_LATEX.format(expression)) + .append("\n"); + } + }.create(); + return sb.toString(); + } + + private final class SizeAction extends AbstractAction { private int n; @@ -472,12 +507,12 @@ public class TableDialog extends JDialog { } } - private class BuiderExpressionCreator extends ExpressionCreator { + private class BuilderExpressionCreator extends ExpressionCreator { private final HashSet contained; private final BuilderInterface builder; private final ExpressionModifier[] modifier; - BuiderExpressionCreator(BuilderInterface builder, ExpressionModifier... modifier) { + BuilderExpressionCreator(BuilderInterface builder, ExpressionModifier... modifier) { super(TableDialog.this.model.getTable()); contained = new HashSet<>(); this.builder = builder; diff --git a/src/main/resources/lang/lang_de.properties b/src/main/resources/lang/lang_de.properties index 90f8ecf6a..7c16dca22 100644 --- a/src/main/resources/lang/lang_de.properties +++ b/src/main/resources/lang/lang_de.properties @@ -321,7 +321,7 @@ menu_table_createCUPL_tt=Erzeugt eine CUPL Quelldatei welche die Schaltung besch menu_table_create_hardware=Bausteine menu_table_create_gal16v8=GAL16v8 und kompatible menu_table_create_gal16v8_tt=Erzeugt eine JEDEC Datei f\u00FCr ein GAL16v8 - +menu_table_exportTableLaTeX=Export LaTeX menu_editSettings=Einstellungen menu_editSettings_tt=Bearbeitet die globalen Einstellungen @@ -339,3 +339,5 @@ win_listing=Listing win_table=Tabelle win_allSolutions=Alle m\u00F6glichen L\u00F6sungen win_pinMapDialog=Pin-Zuordnung +win_table_exportDialog=Export + diff --git a/src/main/resources/lang/lang_en.properties b/src/main/resources/lang/lang_en.properties index fe9079b3d..cb9655329 100644 --- a/src/main/resources/lang/lang_en.properties +++ b/src/main/resources/lang/lang_en.properties @@ -299,6 +299,7 @@ menu_table_createCUPL_tt=Creates a CUPL source file containing the define circui menu_table_create_hardware=Device menu_table_create_gal16v8=GAL16v8 and compatible devices menu_table_create_gal16v8_tt=Creates a JEDEC file for a GAL16v8 +menu_table_exportTableLaTeX=Export LaTeX menu_editSettings=Settings menu_editSettings_tt=Edits Digitals Preferences @@ -311,6 +312,7 @@ win_measures_microstep=Measurements single gate step win_measures_fullstep=Measurements full clock step win_listing=Listing win_pinMapDialog=Pin Mapping +win_table_exportDialog=Export key_InputSplitting_tt=Example "4,2,2" or "[Bits]*[Count] like "1*16" for 16 single bits key_OutputSplitting_tt=Example "4,2,2" or "[Bits]*[Count] like "1*16" for 16 single bits diff --git a/src/test/java/de/neemann/digital/analyse/expression/format/FormatterTest.java b/src/test/java/de/neemann/digital/analyse/expression/format/FormatterTest.java index 19b635004..b54bf12dd 100644 --- a/src/test/java/de/neemann/digital/analyse/expression/format/FormatterTest.java +++ b/src/test/java/de/neemann/digital/analyse/expression/format/FormatterTest.java @@ -45,10 +45,10 @@ public class FormatterTest extends TestCase { public void testFormatExpLaTeX() throws Exception, FormatterException { - Variable a = new Variable("An"); - Variable b = new Variable("Bn"); + Variable a = new Variable("A_n"); + Variable b = new Variable("B_n"); Expression e = and(a, not(b)); - assertEquals("Y_{n+1}=A_{n} \\und \\nicht{B_{n}}", FormatToExpression.FORMATTER_LATEX.format("Yn+1", e)); + assertEquals("Y_{n+1}=A_{n} \\und \\nicht{B_{n}}", FormatToExpression.FORMATTER_LATEX.format("Y_n+1", e)); } diff --git a/src/test/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeXTest.java b/src/test/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeXTest.java new file mode 100644 index 000000000..e273af967 --- /dev/null +++ b/src/test/java/de/neemann/digital/analyse/format/TruthTableFormatterLaTeXTest.java @@ -0,0 +1,32 @@ +package de.neemann.digital.analyse.format; + +import de.neemann.digital.analyse.TruthTable; +import junit.framework.TestCase; + +/** + * @author hneemann + */ +public class TruthTableFormatterLaTeXTest extends TestCase { + + public void testFormat() throws Exception { + TruthTable tt = new TruthTable(3); + tt.addResult("Y_0"); + tt.addResult("Y_1"); + + assertEquals("\\begin{center}\n" + + "\\begin{tabular}{ccc|cc}\n" + + "$A$&$B$&$C$&$Y_{0}$&$Y_{1}$\\\\\n" + + "\\hline\n" + + "$0$&$0$&$0$&$0$&$0$\\\\\n" + + "$0$&$0$&$1$&$0$&$0$\\\\\n" + + "$0$&$1$&$0$&$0$&$0$\\\\\n" + + "$0$&$1$&$1$&$0$&$0$\\\\\n" + + "$1$&$0$&$0$&$0$&$0$\\\\\n" + + "$1$&$0$&$1$&$0$&$0$\\\\\n" + + "$1$&$1$&$0$&$0$&$0$\\\\\n" + + "$1$&$1$&$1$&$0$&$0$\\\\\n" + + "\\end{tabular}\n" + + "\\end{center}\n", new TruthTableFormatterLaTeX().format(tt)); + } + +} \ No newline at end of file