package code.generators; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; /** *

* Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights * reserved.
* BSD-style license. See OpenTrafficSim License. *

* $LastChangedDate$, @version $Revision$, by $Author: pknoppers * $, initial version 6 okt. 2014
* @author Peter Knoppers */ public class ValueTestsGenerator { /** * Generate the test classes for the value classes. * @param args String[]; the command line arguments (ignored) */ public static void main(final String[] args) { Date now = new Date(); CodeGenerator cg = new CodeGenerator("the OpenTrafficSim value test classes generator", "d:\\java\\ots-core\\src\\test\\java\\org\\opentrafficsim\\core\\value", "org.opentrafficsim.core.value", new SimpleDateFormat("dd MMM, yyyy").format(now), new Long( new SimpleDateFormat("yyyyMMdd").format(now))); for (String type : new String[]{"Float", "Double"}) { for (int dimensions = 0; dimensions <= 2; dimensions++) { if (dimensions > 0) { generateClass(cg, dimensions, type, "Dense"); generateClass(cg, dimensions, type, "Sparse"); } else { generateClass(cg, dimensions, type, null); } } } } /** * @param cg CodeGenerator * @param dimensions int; number of dimensions of the stored value(s) * @param type String; Float, or Double * @param denseness String; Dense, Sparse, or null */ private static void generateClass(final CodeGenerator cg, final int dimensions, final String type, final String denseness) { final String aggregate = 0 == dimensions ? "Scalar" : 1 == dimensions ? "Vector" : "Matrix"; final String otscu = "org.opentrafficsim.core.unit."; final String pragma = "@SuppressWarnings(\"static-method\")\r\n" + cg.indent(1) + "@Test"; final String suffix = type.startsWith("F") ? "f" : ""; final String ds = null == denseness ? "" : denseness; final String dotDS = null == denseness ? "" : "." + ds; final String zeroArgs = (dimensions > 0 ? "0, " : "") + (dimensions > 1 ? "0, " : ""); final String zeroArgsNoComma = (dimensions > 0 ? "0" : "") + (dimensions > 1 ? ", 0" : ""); final String firstIndexName = 1 == dimensions ? "index" : "row"; final String firstIndexRange = 1 == dimensions ? "size" : "rows"; StringBuilder code = new StringBuilder(); code.append(generateInitializer(cg, dimensions, type)); final String shortName = type.substring(0, 1).toLowerCase() + aggregate.substring(0, 1).toLowerCase(); code.append(cg.buildMethod(cg.indent(1), "private static|void|checkContentsAndType", "Check that the value" + (dimensions > 0 ? "s" : "") + " in a " + type + aggregate + (dimensions > 0 ? "match" : "matches") + " the expected value" + (dimensions > 0 ? "s" : "") + ".", new String[]{ "final " + type + aggregate + "|" + shortName + "|the " + type + aggregate + " to match", "final " + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + "|reference|the reference value" + (dimensions > 0 ? "s" : ""), "final " + type.toLowerCase() + "|precision|the maximum allowed error", "final Unit|u|the expected type", "final boolean|expectAbsolute|if true; " + shortName + " should be Absolute; if false; " + shortName + " should be Relative"}, null, null, new String[]{ "assertTrue(\"" + type + aggregate + " should not be null\", null != " + shortName + ");", 0 == dimensions ? "assertEquals(\"Value should match\", reference, " + shortName + ".getInUnit(), precision);" : null, dimensions > 0 ? "for (int " + firstIndexName + " = " + shortName + "." + firstIndexRange + "(); --" + firstIndexName + " >= 0;)" : null, dimensions > 0 ? "{" : null, 2 == dimensions ? cg.indent(1) + "for (int column = " + shortName + ".columns(); --column >= 0;)" : null, 2 == dimensions ? cg.indent(2) + "{" : null, dimensions > 0 ? cg.indent(dimensions) + "try" : null, dimensions > 0 ? cg.indent(dimensions) + "{" : null, dimensions > 0 ? cg.indent(dimensions + 1) + "assertEquals(\"Value should match\", reference[" + firstIndexName + (dimensions == 1 ? "" : "][column") + "], " + shortName + ".getInUnit(" + firstIndexName + (dimensions == 1 ? "" : ", column") + "), precision);" : null, dimensions > 0 ? cg.indent(dimensions) + "}" : null, dimensions > 0 ? cg.indent(dimensions) + "catch (ValueException exception)" : null, dimensions > 0 ? cg.indent(dimensions) + "{" : null, dimensions > 0 ? cg.indent(dimensions + 1) + "fail(\"Unexpected exception\");" : null, dimensions > 1 ? cg.indent(dimensions) + "}" : null, dimensions > 0 ? cg.indent(1) + "}" : null, dimensions > 0 ? "}" : null, "assertEquals(\"Unit should be \" + u.toString(), u, " + shortName + ".getUnit());", "assertTrue(\"Should be \" + (expectAbsolute ? \"Absolute\" : \"Relative\"), ", cg.indent(3) + "expectAbsolute ? " + shortName + ".isAbsolute() : " + shortName + ".isRelative());"}, false)); for (String absoluteRelative : new String[]{"Absolute", "Relative"}) { final String absRel = absoluteRelative.substring(0, 3); for (String mutable : new String[]{"", "Mutable"}) { final String in = cg.indent(dimensions > 1 ? 1 : 0); code.append(cg.buildMethod( cg.indent(1), "public final|void|toString" + mutable + absRel + "Test", "Test that the toString method returns something sensible.", null, null, pragma, new String[]{ dimensions > 0 ? "try" : null, dimensions > 0 ? "{" : null, in + "TemperatureUnit tempUnit = TemperatureUnit.KELVIN;", in + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " value = " + makeInitializer(type, dimensions, "38.0", false) + ";", in + mutable + type + aggregate + "." + absRel + dotDS + " " + shortName + " = new " + mutable + type + aggregate + "." + absRel + dotDS + "(value, tempUnit);", in + "String result = " + shortName + ".toString(true, true);", // "System.out.println(result);", in + "assertTrue(\"toString result contains \\\" " + absRel + " \\\"\", result.contains(\" " + absRel + " \"));", in + "assertTrue(\"toString result contains \\\"K\\\"\", result.contains(\"K\"));", in + "assertTrue(\"toString result starts with \\\"Immutable \\\"\", " + "result.startsWith(\"" + (mutable.length() > 0 ? "Mutable" : "Immutable") + "\"));", dimensions > 0 && null != denseness ? in + "assertTrue(\"toString contains \\\"" + denseness + "\\\"\", result.contains(\"" + denseness + "\"));" : null, dimensions > 0 ? "}" : null, dimensions > 0 ? "catch (ValueException ve)" : null, dimensions > 0 ? "{" : null, dimensions > 0 ? cg.indent(1) + "fail(\"Caught unexpected exception: \" + ve.toString());" : null, dimensions > 0 ? "}" : null}, false)); } final String varName1 = "temperature" + type.substring(0, 1) + aggregate.substring(0, 1).toUpperCase(); final String varName2 = "temperature2" + type.substring(0, 1) + aggregate.substring(0, 1).toUpperCase(); final String in = dimensions > 0 ? cg.indent(1) : ""; code.append(cg.buildMethod( cg.indent(1), "public final|void|basics" + absRel + "Test", "Test constructor, verify the various fields in the constructed objects, test conversions to " + "related units.", null, null, dimensions == 0 ? pragma : "@SuppressWarnings({\"static-method\", \"unchecked\"})\r\n" + cg.indent(1) + "@Test", new String[]{ dimensions > 0 ? "try" : null, dimensions > 0 ? "{" : null, in + "TemperatureUnit tempUnit = TemperatureUnit.DEGREE_CELSIUS;", in + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " value = " + makeInitializer(type, dimensions, "38.0", false) + ";", in + type + aggregate + "." + absRel + dotDS + " " + varName1 + " = new " + type + aggregate + "." + absRel + dotDS + "(value, tempUnit);", in + "checkContentsAndType(" + varName1 + ", value, 0.001" + suffix + ", tempUnit, " + absoluteRelative.startsWith("A") + ");", in + "assertEquals(\"Value in SI is equivalent in Kelvin\", 311.15" + suffix + ", " + varName1 + ".getSI(" + zeroArgsNoComma + "), 0.05);", in + "assertEquals(\"Value in Fahrenheit\", 100.4" + suffix + ", " + varName1 + ".getInUnit(" + zeroArgs + "TemperatureUnit.DEGREE_FAHRENHEIT), 0.1);", in + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " out = " + varName1 + ".get" + (dimensions > 0 ? "Values" : "") + "InUnit();", dimensions > 0 ? in + "for (int " + firstIndexName + " = 0; " + firstIndexName + " < value.length; " + firstIndexName + "++)" : null, dimensions > 0 ? in + "{" : null, dimensions > 1 ? in + cg.indent(1) + "for (int column = 0; column < value[row].length; column++)" : null, dimensions > 1 ? in + cg.indent(1) + "{" : null, in + cg.indent(dimensions) + "assertEquals(\"Value should match\", value" + (dimensions > 0 ? "[" + firstIndexName + "]" : "") + (dimensions > 1 ? "[column]" : "") + ", out" + (dimensions > 0 ? "[" + firstIndexName + "]" : "") + (dimensions > 1 ? "[column]" : "") + ", 0.001);", dimensions > 1 ? in + cg.indent(1) + "}" : null, dimensions > 0 ? in + "}" : null, in + "Mutable" + type + aggregate + "." + absRel + dotDS + " m" + shortName + " = new Mutable" + type + aggregate + "." + absRel + dotDS + "(value, tempUnit);", in + "checkContentsAndType(m" + shortName + ", value, 0.001" + suffix + ", tempUnit, " + absoluteRelative.startsWith("A") + ");", in + "m" + shortName + ".setSI(" + zeroArgs + "73);", in + type.toLowerCase() + " safe = value" + cg.buildBrackets(dimensions, "0") + ";", in + "value" + cg.buildBrackets(dimensions, "0") + " = -200; // Approximate Celsius equivalent of 73 Kelvin", in + "checkContentsAndType(m" + shortName + ", value, 1" + ", tempUnit, " + absoluteRelative.startsWith("A") + ");", in + "value" + cg.buildBrackets(dimensions, "0") + " = safe; // Restore", in + "m" + shortName + ".set(" + (dimensions > 0 ? "0, " : "") + (dimensions > 1 ? "0, " : "") + varName1 + (dimensions > 0 ? ".get(0" + (dimensions > 1 ? ", 0)" : ")") : "") + ");", in + "checkContentsAndType(m" + shortName + ", value, 0.001" + suffix + ", tempUnit, " + absoluteRelative.startsWith("A") + ");", in + type + aggregate + "." + absRel + dotDS + " " + varName2 + " = new " + type + aggregate + "." + absRel + dotDS + "(" + varName1 + (dimensions > 0 ? ".get" + aggregate + "SI(), TemperatureUnit.KELVIN" : "") + ");", in + "assertTrue(\"" + varName2 + " should be equal to " + varName1 + "\", " + varName2 + ".equals(" + varName1 + "));", in + "assertTrue(\"Value is " + absoluteRelative + "\", " + varName1 + ".is" + absoluteRelative + "());", in + "assertFalse(\"Value is not " + (absoluteRelative.startsWith("A") ? "Relative" : "Absolute") + "\", " + varName1 + ".is" + (absoluteRelative.startsWith("A") ? "Relative" : "Absolute") + "());", in + varName1 + " = new " + type + aggregate + "." + absRel + dotDS + "(value, TemperatureUnit.KELVIN);", in + "checkContentsAndType(" + varName1 + ", value, 0.001" + suffix + ", TemperatureUnit.KELVIN, " + absoluteRelative.startsWith("A") + ");", in + "out = " + varName1 + ".get" + (dimensions > 0 ? "Values" : "") + "SI();", dimensions > 0 ? in + "for (int " + firstIndexName + " = 0; " + firstIndexName + " < value.length; " + firstIndexName + "++)" : null, dimensions > 0 ? in + "{" : null, dimensions > 1 ? in + cg.indent(1) + "for (int column = 0; column < value[row].length; column++)" : null, dimensions > 1 ? in + cg.indent(1) + "{" : null, in + cg.indent(dimensions) + "assertEquals(\"Value should match\", value" + (dimensions > 0 ? "[" + firstIndexName + "]" : "") + (dimensions > 1 ? "[column]" : "") + ", out" + (dimensions > 0 ? "[" + firstIndexName + "]" : "") + (dimensions > 1 ? "[column]" : "") + ", 0.001);", dimensions > 1 ? in + cg.indent(1) + "}" : null, dimensions > 0 ? in + "}" : null, dimensions > 0 ? in + type + "Scalar." + absRel + "" + cg.buildEmptyBrackets(dimensions) + " scalar = new " + type + "Scalar." + absRel + "[value.length]" + cg.buildEmptyBrackets(dimensions - 1) + ";" : null, dimensions > 0 ? "for (int " + firstIndexName + " = 0; " + firstIndexName + " < value.length; " + firstIndexName + "++)" : null, dimensions > 0 ? in + "{" : null, dimensions > 1 ? in + cg.indent(1) + "scalar[row] = new " + type + "Scalar." + absRel + "[value[row].length];" : null, dimensions > 1 ? in + cg.indent(1) + "for (int column = 0; column < value[row].length; column++)" : null, dimensions > 1 ? in + cg.indent(1) + "{" : null, dimensions > 0 ? in + cg.indent(dimensions) + "scalar[" + (dimensions > 0 ? firstIndexName : "") + "]" + (dimensions > 1 ? "[column]" : "") + " = new " + type + "Scalar." + absRel + "(value[" + (dimensions > 0 ? firstIndexName : "") + (dimensions > 1 ? "][column" : "") + "], TemperatureUnit.DEGREE_CELSIUS);" : null, dimensions > 1 ? in + cg.indent(1) + "}" : null, dimensions > 0 ? in + "}" : null, dimensions > 0 ? in + varName1 + " = new " + type + aggregate + "." + absRel + dotDS + "(scalar);" : null, dimensions > 0 ? in + "checkContentsAndType(" + varName1 + ", value, 0.001" + suffix + ", tempUnit, " + absoluteRelative.startsWith("A") + ");" : null, dimensions > 0 ? in + "assertEquals(\"All cells != 0; cardinality should equal number of " + "cells\", value.length" + (dimensions > 1 ? " * value[0].length" : "") + ", " + varName1 + ".cardinality());" : null, dimensions > 0 ? in + type.toLowerCase() + " sum = 0;" : null, dimensions > 0 ? in + "for (int " + firstIndexName + " = 0; " + firstIndexName + " < value.length; " + firstIndexName + "++)" : null, dimensions > 0 ? in + "{" : null, dimensions > 1 ? in + cg.indent(1) + "scalar[row] = new " + type + "Scalar." + absRel + "[value[row].length];" : null, dimensions > 1 ? in + cg.indent(1) + "for (int column = 0; column < value[row].length; column++)" : null, dimensions > 1 ? in + cg.indent(1) + "{" : null, dimensions > 0 ? in + cg.indent(dimensions) + "sum += " + varName1 + ".getSI(" + (dimensions > 0 ? firstIndexName : "") + (dimensions > 1 ? ", column" : "") + ");" : null, dimensions > 1 ? in + cg.indent(1) + "}" : null, dimensions > 0 ? in + "}" : null, dimensions > 0 ? in + "assertEquals(\"zSum should be sum of all values\", sum, " + varName1 + ".zSum(), 0.001);" : null, 0 == dimensions ? "for (int i = -100; i <= 100; i++)" : null, 0 == dimensions ? "{" : null, 0 == dimensions ? cg.indent(1) + type.toLowerCase() + " v = i / 10.0" + suffix + ";" : null, 0 == dimensions ? cg.indent(1) + "m" + shortName + ".setSI(v);" : null, 0 == dimensions ? cg.indent(1) + "assertEquals(\"intValue should round like Math.round\", Math.round(v), m" + shortName + ".intValue(), 0.0001);" : null, 0 == dimensions ? cg.indent(1) + "assertEquals(\"longValue should round like Math.round\", Math.round(v), m" + shortName + ".longValue(), 0.0001);" : null, 0 == dimensions ? cg.indent(1) + "assertEquals(\"floatValue should return the value\", v, m" + shortName + ".floatValue(), 0.0001);" : null, 0 == dimensions ? cg.indent(1) + "assertEquals(\"doubleValue should return the value\", v, m" + shortName + ".doubleValue(), 0.0001);" : null, dimensions > 0 ? "}" : null, dimensions > 0 ? "catch (ValueException ve)" : null, dimensions > 0 ? "{" : null, dimensions > 0 ? cg.indent(1) + "fail(\"Caught unexpected ValueException: \" + ve.toString());" : null, "}"}, false)); final String mutableName = "m" + shortName; final String mutableMutableName = "m" + mutableName; final String secondImmutableName = "i" + shortName; final String copyName = shortName + "Copy"; final String mutableCopyName = mutableName + "Copy"; code.append(cg.buildMethod( cg.indent(1), "public final|void|toMutableAndBack" + absRel + "Test", "Test conversion to mutable equivalent and back.", null, null, pragma, new String[]{ dimensions > 0 ? "try" : null, dimensions > 0 ? "{" : null, in + "TemperatureUnit tempUnit = TemperatureUnit.DEGREE_CELSIUS;", in + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " value = " + makeInitializer(type, dimensions, "38.0", false) + ";", in + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " value2 = " + makeInitializer(type, dimensions, "38.0", false) + ";", in + "value2" + cg.buildBrackets(dimensions, "0") + " = 12345;", in + type + aggregate + "." + absRel + dotDS + " " + shortName + " = new " + type + aggregate + "." + absRel + dotDS + "(value, tempUnit);", in + type + aggregate + "." + absRel + " " + copyName + " = " + shortName + ".copy();", in + "Mutable" + type + aggregate + "." + absRel + dotDS + " " + mutableName + " = " + shortName + ".mutable();", in + "checkContentsAndType(" + shortName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "checkContentsAndType(" + mutableName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "checkContentsAndType(" + copyName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "Mutable" + type + aggregate + "." + absRel + dotDS + " " + mutableCopyName + " = " + mutableName + ".copy();", in + "checkContentsAndType(" + mutableCopyName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "Mutable" + type + aggregate + "." + absRel + dotDS + " " + mutableMutableName + " = " + mutableName + ".mutable();", in + "checkContentsAndType(" + mutableMutableName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "assertEquals(\"hashCode is independent on mutability\", " + shortName + ".hashCode(), " + mutableName + ".hashCode());", in + "// Modify " + mutableName, in + mutableName + ".setInUnit" + "(" + zeroArgs + "12345, TemperatureUnit.DEGREE_CELSIUS);", in + "checkContentsAndType(" + shortName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "checkContentsAndType(" + mutableName + ", value2, 0.01" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "checkContentsAndType(" + mutableCopyName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "checkContentsAndType(" + mutableMutableName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + type + aggregate + "." + absRel + " " + secondImmutableName + " = " + mutableName + ".immutable();", in + "assertTrue(\"Different value extremely likely results in different hashCode\", " + shortName + ".hashCode() != " + mutableName + ".hashCode());", in + "// Restore value of " + mutableName, in + mutableName + ".set" + (0 == dimensions ? "Value" : "") + "SI(" + zeroArgs + shortName + ".getSI(" + zeroArgsNoComma + "));", in + "checkContentsAndType(" + secondImmutableName + ", value2, 0.01" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "checkContentsAndType(" + mutableName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "checkContentsAndType(" + mutableMutableName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + mutableMutableName + ".setSI(" + zeroArgs + "0);", in + "checkContentsAndType(" + mutableName + ", value, 0.001" + suffix + ", tempUnit, " + absRel.startsWith("A") + ");", in + "assertEquals(\"value should be about -273\", -273, " + mutableMutableName + ".getInUnit(" + zeroArgs + "tempUnit), 0.2);", dimensions > 0 ? "}" : null, dimensions > 0 ? "catch (ValueException ve)" : null, dimensions > 0 ? "{" : null, dimensions > 0 ? cg.indent(1) + "fail(\"Caught unexpected exception: \" + ve.toString());" : null, dimensions > 0 ? "}" : null}, false)); final String absRelInverse = absRel.startsWith("A") ? "Rel" : "Abs"; code.append(cg.buildMethod(cg.indent(1), "public final|void|equals" + absRel + "Test", "Test the equals method.", null, null, pragma, new String[]{ "LengthUnit lengthUnit = LengthUnit.METER;", type.toLowerCase() + " value = 38.0" + suffix + ";", type + "Scalar." + absRel + " " + shortName + " = new " + type + "Scalar." + absRel + "(value, lengthUnit);", "assertTrue(\"Equal to itself\", " + shortName + ".equals(" + shortName + "));", "assertFalse(\"Not equal to null\", " + shortName + ".equals(null));", "assertFalse(\"Not equal to some other kind of object; e.g. a String\", " + shortName + ".equals(new String(\"abc\")));", type + "Scalar." + absRelInverse + " " + shortName + "CounterPart = new " + type + "Scalar." + absRelInverse + "(value, lengthUnit);", "assertFalse(\"Not equal if one Absolute and other Relative\", " + shortName + ".equals(" + shortName + "CounterPart));", type + "Scalar." + absRel + " " + shortName + "WrongBaseUnit = new " + type + "Scalar." + absRel + "(value, TemperatureUnit.KELVIN);", "assertEquals(\"The underlying SI values are the same\", " + shortName + ".getSI(), " + shortName + "WrongBaseUnit.getSI(), 0.0001" + suffix + ");", "assertFalse(\"Not equals because the standard SI unit differs\", " + shortName + ".equals(" + shortName + "WrongBaseUnit));", type + "Scalar." + absRel + " " + shortName + "CompatibleUnit =", cg.indent(2) + "new " + type + "Scalar." + absRel + "(38000.0" + suffix + ", LengthUnit.MILLIMETER);", "assertFalse(\"Units are different\", " + shortName + ".getUnit().equals(" + shortName + "CompatibleUnit.getUnit()));", "assertTrue(\"equals returns true\", " + shortName + ".equals(" + shortName + "CompatibleUnit));", type + "Scalar." + absRel + " " + shortName + "DifferentValue =", cg.indent(2) + "new " + type + "Scalar." + absRel + "(123.456" + suffix + ", LengthUnit.MILLIMETER);", "assertFalse(\"Different value makes equals return false\", " + shortName + ".equals(" + shortName + "DifferentValue));" }, false)); if (0 == dimensions) { for (String base : new String[]{"", "Mutable"}) { final String oppositeBase = base.equals("") ? "Mutable" : ""; code.append(cg.buildMethod(cg.indent(1), "public final|void|relOp" + base + absRel + "Test", "Test the relational operations", null, null, pragma, new String[]{ base + type + "Scalar." + absRel + " base = new " + base + type + "Scalar." + absRel + "(123, LengthUnit.KILOMETER);", base + type + "Scalar." + absRel + " same = new " + base + type + "Scalar." + absRel + "(123000, LengthUnit.METER);", base + type + "Scalar." + absRel + " smaller = new " + base + type + "Scalar." + absRel + "(122999, LengthUnit.METER);", base + type + "Scalar." + absRel + " larger = new " + base + type + "Scalar." + absRel + "(123001, LengthUnit.METER);", "assertFalse(\"123km < 123000m\", base.lt(same));", "assertTrue(\"123km <= 123000m\", base.le(same));", "assertTrue(\"123km >= 123000m\", base.ge(same));", "assertFalse(\"NOT 123km > 123000m\", base.gt(same));", "assertTrue(\"123km == 123000m\", base.eq(same));", "assertFalse(\"NOT 123km != 123000m\", base.ne(same));", "assertTrue(\"123km < 123001m\", base.lt(larger));", "assertTrue(\"123km > 122999m\", base.gt(smaller));", "assertTrue(\"123km >= 123000m\", base.ge(same));", "assertFalse(\"NOT 123km > 123000m\", base.gt(same));", "assertFalse(\"NOT 123km < 123000m\", base.lt(same));", "assertTrue(\"123km <= 123000m\", base.le(same));", "assertTrue(\"123km != 123001m\", base.ne(larger));", "assertFalse(\"NOT 123km == 123001m\", base.eq(larger));", "assertTrue(\"123km != 122999m\", base.ne(smaller));", "assertFalse(\"NOT 123km == 122999m\", base.eq(smaller));", "assertFalse(\"NOT 123km >= 123001m\", base.ge(larger));", "assertFalse(\"NOT 123km <= 122999m\", base.le(smaller));", oppositeBase + type + "Scalar." + absRel + " same2 = new " + oppositeBase + type + "Scalar." + absRel + "(123000, LengthUnit.METER);", oppositeBase + type + "Scalar." + absRel + " smaller2 = new " + oppositeBase + type + "Scalar." + absRel + "(122999, LengthUnit.METER);", oppositeBase + type + "Scalar." + absRel + " larger2 = new " + oppositeBase + type + "Scalar." + absRel + "(123001, LengthUnit.METER);", "assertFalse(\"NOT 123km < 123000m\", base.lt(same2));", "assertTrue(\"123km <= 123000m\", base.le(same2));", "assertTrue(\"123km >= 123000m\", base.ge(same2));", "assertFalse(\"NOT 123km > 123000m\", base.gt(same2));", "assertTrue(\"123km == 123000m\", base.eq(same2));", "assertFalse(\"NOT 123km != 123000m\", base.ne(same2));", "assertTrue(\"123km < 123001m\", base.lt(larger2));", "assertTrue(\"123km > 122999m\", base.gt(smaller2));", "assertTrue(\"123km >= 123000m\", base.ge(same2));", "assertFalse(\"NOT 123km > 123000m\", base.gt(same2));", "assertFalse(\"NOT 123km < 123000m\", base.lt(same2));", "assertTrue(\"123km <= 123000m\", base.le(same2));", "assertTrue(\"123km != 123001m\", base.ne(larger2));", "assertFalse(\"NOT 123km == 123001m\", base.eq(larger2));", "assertTrue(\"123km != 122999m\", base.ne(smaller2));", "assertFalse(\"NOT 123km == 122999m\", base.eq(smaller2));", "assertFalse(\"NOT 123km >= 123001m\", base.ge(larger2));", "assertFalse(\"NOT 123km <= 122999m\", base.le(smaller2));"}, false)); } } ArrayList mathCode = new ArrayList(); final String varName = type.toLowerCase().substring(0, 1); mathCode.add(type.toLowerCase() + "[] seedValues = {-10" + suffix + ", -2" + suffix + ", -1" + suffix + ", -0.5" + suffix + ", -0.1" + suffix + ", 0" + suffix + ", 0.1" + suffix + ", 0.5" + suffix + ", 1" + suffix + ", 2" + suffix + ", 10" + suffix + "};"); mathCode.add("for (" + type.toLowerCase() + " seedValue : seedValues)"); mathCode.add("{"); mathCode.add(cg.indent(1) + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " input = " + makeInitializer(type, dimensions, "seedValue", false) + ";"); mathCode.add(cg.indent(1) + "Mutable" + type + aggregate + "." + absRel + dotDS + " " + shortName + ";"); if (dimensions > 0) { mathCode.add(cg.indent(1) + "try"); mathCode.add(cg.indent(1) + "{"); } for (MathFunction mf : MathFunction.mathFunctions) { final int baseIndent = (null == mf.argument ? 1 : 2) + (dimensions > 0 ? 1 : 0); if (null != mf.argument) { mathCode.add(cg.indent(1) + "for (int i = -10; i <= 10; i++)"); mathCode.add(cg.indent(1) + "{"); mathCode.add(cg.indent(2) + "final " + type.toLowerCase() + " exponent = i * 0.5" + type.toLowerCase().substring(0, 1) + ";"); } mathCode.add(cg.indent(baseIndent) + shortName + " = new Mutable" + type + aggregate + "." + absRel + dotDS + "(input, LengthUnit.METER);"); mathCode.add(cg.indent(baseIndent) + shortName + "." + mf.name + "(" + (null != mf.argument ? "exponent" : "") + ");"); mathCode.add(cg.indent(baseIndent) + "MathTester.tester(input, \"" + mf.name + (null != mf.argument ? "(\" + exponent + \")" : "") + "\", " + shortName + ", 0.001, new " + type + "To" + type + "()"); mathCode.add(cg.indent(baseIndent) + "{"); mathCode.add(cg.indent(baseIndent + 1) + "@Override"); mathCode.add(cg.indent(baseIndent + 1) + "public " + type.toLowerCase() + " function(final " + type.toLowerCase() + " " + varName + ")"); mathCode.add(cg.indent(baseIndent + 1) + "{"); mathCode.add(cg.indent(baseIndent + 2) + "return " + (mf.name.equals("inv") ? "1 / " + varName : (mf.castToFloatRequired && type.startsWith("F") ? "(float) " : "") + "Math." + mf.name + "(" + varName + (null != mf.argument ? ", exponent" : "") + ")") + ";"); mathCode.add(cg.indent(baseIndent + 1) + "}"); mathCode.add(cg.indent(baseIndent) + "});"); if (null != mf.argument) { mathCode.add(cg.indent(1) + "}"); } } if (dimensions > 0) { mathCode.add(cg.indent(1) + "}"); mathCode.add(cg.indent(1) + "catch (ValueException ve)"); mathCode.add(cg.indent(1) + "{"); mathCode.add(cg.indent(2) + "fail(\"Caught unexpected ValueException: \" + ve.toString());"); mathCode.add(cg.indent(1) + "}"); } mathCode.add("}"); code.append(cg.buildMethod(cg.indent(1), "public final|void|mathFunctionsTest" + absRel + "Test", "Test the Math functions.", null, null, pragma, CodeGenerator.arrayListToArray(mathCode), false)); String[] dsCombinations = dotDS.length() == 0 ? new String[]{""} : new String[]{".Dense", ".Sparse"}; for (String otherDotDS : dsCombinations) { code.append(twoOpChecker(cg, type, dimensions, absRel + dotDS, "Rel" + otherDotDS, absRel + (dotDS.contains("Dense") || otherDotDS.contains("Dense") ? ".Dense" : dotDS), "plus", "+")); code.append(twoOpChecker(cg, type, dimensions, absRel + dotDS, "Rel" + otherDotDS, absRel + (dotDS.contains("Dense") || otherDotDS.contains("Dense") ? ".Dense" : dotDS), "minus", "-")); code.append(twoOpChecker(cg, type, dimensions, absRel + dotDS, absRel + otherDotDS, absRel + (dotDS.contains("Sparse") || otherDotDS.contains("Sparse") ? ".Sparse" : dotDS), 0 == dimensions ? "multiply" : "times", "*")); if (0 == dimensions) { code.append(twoOpChecker(cg, type, dimensions, absRel + dotDS, absRel + dotDS, absRel + dotDS, "divide", "/")); } } if (dimensions > 0) { ArrayList checkCode = new ArrayList(); checkCode.add("int junk = 0;"); checkCode.addAll(wrap(cg, "", new String[]{ "// null array", "new " + type + aggregate + "." + absRel + dotDS + "((" + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + ") null, TemperatureUnit.DEGREE_FAHRENHEIT);"})); if (dimensions > 1) { checkCode.addAll(wrap( cg, "", new String[]{ "// Matrix with null on first row", type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " in = " + makeInitializer(type, dimensions, "12.3", false) + ";", "in[0] = null;", "new " + type + aggregate + "." + absRel + dotDS + "(in, TemperatureUnit.DEGREE_CELSIUS);"})); checkCode.addAll(wrap( cg, "", new String[]{ "// Matrix with null on last row", type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " in = " + makeInitializer(type, dimensions, "12.3", false) + ";", "in[in.length - 1] = null;", "new " + type + aggregate + "." + absRel + dotDS + "(in, TemperatureUnit.DEGREE_CELSIUS);"})); checkCode.addAll(wrap( cg, "", new String[]{ "// Non-rectangular array", type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " in = " + makeInitializer(type, dimensions, "12.3", true) + ";", "new " + type + aggregate + "." + absRel + dotDS + "(in, TemperatureUnit.DEGREE_CELSIUS);"})); checkCode.add("// Determinant of non-square Matrix"); checkCode.add(type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " in = " + makeInitializer(type, dimensions, "12.3", false) + ";"); checkCode.addAll(wrap(cg, "", new String[]{ type + aggregate + "." + absRel + dotDS + " matrix = null;", "try", "{", cg.indent(1) + "matrix = new " + type + aggregate + "." + absRel + dotDS + "(in, TemperatureUnit.DEGREE_CELSIUS);", "}", "catch (ValueException ve)", "{", cg.indent(1) + "fail(\"Caught unexpected exception: \" + ve.toString());", "}", "matrix.det();"})); checkCode.addAll(wrap(cg, "", new String[]{ type + aggregate + "." + absRel + dotDS + " matrix = null;", type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " rowCountWrong = null;", "try", "{", cg.indent(1) + "matrix = new " + type + aggregate + "." + absRel + dotDS + "(in, TemperatureUnit.DEGREE_CELSIUS);", cg.indent(1) + " rowCountWrong = data(4, 5, false, 2);", "}", "catch (ValueException ve)", "{", cg.indent(1) + "fail(\"Caught unexpected exception: \" + ve.toString());", "}", type + aggregate + ".times(matrix, rowCountWrong);"})); } checkCode.add("assertTrue(\"The variable junk is only used to suppress annoying warnings of the code " + "checker\", junk > 0);"); code.append(cg.buildMethod(cg.indent(1), "public final|void|sizeCheck" + absRel + "Test", "Test that malformed or mismatching arrays throw a ValueException.", null, null, pragma, CodeGenerator.arrayListToArray(checkCode), false)); } if (2 == dimensions) { code.append(cg.buildMethod(cg.indent(1), "public final|void|determinant" + absRel + "Test", "Test the det method that computes and returns the determinant.", null, null, pragma, new String[]{ "try", "{", cg.indent(1) + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " values = {{1, 2, 3 }, {3, 5, 7 }, {5, 10, 0} };", cg.indent(1) + type + aggregate + "." + absRel + dotDS + " matrix = new " + type + aggregate + "." + absRel + dotDS + "(values, TemperatureUnit.KELVIN);", cg.indent(1) + "assertEquals(\"Determinant should be 15\", 15, matrix.det(), 0.001);", "}", "catch (ValueException ve)", "{", cg.indent(1) + "if (ve.toString().contains(\"Matrix must be sparse\"))", cg.indent(1) + "{", cg.indent(2) + "System.err.println(\"Ignoring bug in COLT library\");", cg.indent(2) + "return;", cg.indent(1) + "}", cg.indent(1) + "fail(\"Caught unexpected ValueException: \" + ve.toString());", "}"}, false)); } if (dimensions > 0) { code.append(cg.buildMethod( cg.indent(1), "public final|void|scale" + absRel + "Test", "Test that the times methods with a simple array as the 2nd argument.", null, null, pragma, new String[]{ "try", "{", cg.indent(1) + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " leftIn = " + makeInitializer(type, dimensions, "-12.34" + suffix, false) + ";", cg.indent(1) + type + aggregate + "." + absRel + dotDS + " left = new " + type + aggregate + "." + absRel + dotDS + "(leftIn, TemperatureUnit.KELVIN);", cg.indent(1) + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " right = " + makeInitializer(type, dimensions, "-4.321" + suffix, false) + ";", cg.indent(1) + "Mutable" + type + aggregate + "." + absRel + dotDS + " result = " + type + aggregate + ".times(left, right);", cg.indent(1) + "assertEquals(\"Result should be in Kelvin\", TemperatureUnit.KELVIN, result.getUnit());", cg.indent(1) + "for (int " + firstIndexName + " = right.length; --" + firstIndexName + " >= 0;)", cg.indent(1) + "{", dimensions > 1 ? cg.indent(2) + "for (int column = right[row].length; --column >= 0;)" : null, dimensions > 1 ? cg.indent(2) + "{" : null, cg.indent(dimensions + 1) + "assertEquals(\"Content should match product of left and right\", leftIn[" + firstIndexName + "]" + (dimensions > 1 ? "[column]" : "") + " * right[" + firstIndexName + "]" + (dimensions > 1 ? "[column]" : "") + ", result.getSI(" + firstIndexName + (dimensions > 1 ? ", column" : "") + "), 0.001" + suffix + ");", dimensions > 1 ? cg.indent(2) + "}" : null, cg.indent(1) + "}", "}", "catch (ValueException ve)", "{", cg.indent(1) + "fail(\"Caught unexpected exception: \" + ve.toString());", "}"}, false)); } } code.append(cg.indent(1) + "/** */\r\n"); code.append(cg.indent(1) + "interface " + type + "To" + type + "\r\n"); code.append(cg.indent(1) + "{\r\n"); code.append(cg.indent(2) + "/**\r\n"); code.append(cg.indent(2) + " * @param " + type.toLowerCase().substring(0, 1) + " " + type.toLowerCase() + "; value\r\n"); code.append(cg.indent(2) + " * @return " + type.toLowerCase() + " value\r\n"); code.append(cg.indent(2) + " */\r\n"); code.append(cg.indent(2) + type.toLowerCase() + " function(" + type.toLowerCase() + " " + type.toLowerCase().substring(0, 1) + ");\r\n"); code.append(cg.indent(1) + "}\r\n"); code.append("\r\n"); code.append(cg.indent(1) + "/** */\r\n"); code.append(cg.indent(1) + "abstract static class MathTester\r\n"); code.append(cg.indent(1) + "{\r\n"); code.append(cg.buildMethod( cg.indent(2), "public static|void|tester", "Test a math function.", new String[]{ "final " + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + "|inputValue" + (dimensions > 0 ? "s" : "") + "|unprocessed value", "final String|operation|description of method that is being tested", "final " + type + aggregate + "|actualResult|the actual result of the operation", "final double|precision|expected accuracy", "final " + type + "To" + type + "|function|encapsulated function that converts one " + "inputValue to an outputValue"}, null, null, new String[]{ dimensions > 0 ? "for (int i = 0; i < inputValues.length; i++)" : null, dimensions > 0 ? "{" : null, dimensions > 1 ? cg.indent(1) + "for (int j = 0; j < inputValues[i].length; j++)" : null, dimensions > 1 ? cg.indent(1) + "{" : null, cg.indent(dimensions) + type.toLowerCase() + " expectedResult = function.function(inputValue" + (dimensions > 0 ? "s[i]" + (dimensions > 1 ? "[j]" : "") : "") + ");", cg.indent(dimensions) + type.toLowerCase() + " got = " + (dimensions == 0 ? "actualResult.getSI();" : "0;"), dimensions > 0 ? cg.indent(dimensions) + "try" : null, dimensions > 0 ? cg.indent(dimensions) + "{" : null, dimensions > 0 ? cg.indent(dimensions + 1) + "got = actualResult.getSI(i" + (dimensions > 1 ? ", j" : "") + ");" : null, dimensions > 0 ? cg.indent(dimensions) + "}" : null, dimensions > 0 ? cg.indent(dimensions) + "catch (ValueException ve)" : null, dimensions > 0 ? cg.indent(dimensions) + "{" : null, dimensions > 0 ? cg.indent(dimensions + 1) + "fail(\"Caught unexpected exception: \" + ve.toString());" : null, dimensions > 0 ? cg.indent(dimensions) + "}" : null, cg.indent(dimensions) + "String description =", cg.indent(dimensions + 2) + "String.format(\"%s(%f->%f should be equal to %f with precision %f\", " + "operation, inputValue" + (dimensions > 0 ? "s[i]" + (dimensions > 1 ? "[j]" : "") : "") + ",", cg.indent(dimensions + 4) + "expectedResult, got, precision);", cg.indent(dimensions) + "// System.out.println(description);", cg.indent(dimensions) + "assertEquals(description, expectedResult, got, precision);", dimensions > 1 ? cg.indent(1) + "}" : null, dimensions > 0 ? "}" : null}, false)); code.append(cg.indent(1) + "}\r\n"); code.append("\r\n"); cg.generateClass("v" + type.toLowerCase() + "." + aggregate.toLowerCase(), type + aggregate + (null != denseness ? denseness : "") + "Test", new String[]{"static org.junit.Assert.assertEquals", "static org.junit.Assert.assertFalse", "static org.junit.Assert.assertTrue", dimensions > 0 ? "static org.junit.Assert.fail" : null, "", dimensions > 0 ? "" : null, "org.junit.Test", otscu + "LengthUnit", otscu + "TemperatureUnit", "org.opentrafficsim.core.unit.Unit", dimensions > 0 ? "org.opentrafficsim.core.value.ValueException" : null, "org.opentrafficsim.core.value.v" + type.toLowerCase() + ".scalar." + type + "Scalar"}, "Test the " + type + aggregate + " class.", null, "public", "", false, code.toString()); } /** * Embed Java code in a try - catch construct. * @param cg CodeGenerator; the code generator to use to generate additional indent for the embedded code * @param in String; prefix for all output lines * @param embeddedCode String; Java code to embed in try - catch construct * @return ArrayList<String>; Java code */ private static ArrayList wrap(final CodeGenerator cg, final String in, final String[] embeddedCode) { ArrayList code = new ArrayList(); code.add(in + "try"); code.add(in + "{"); for (String line : embeddedCode) { code.add(in + cg.indent(1) + line); } code.add(in + cg.indent(1) + "fail(\"Preceding code should have thrown a ValueException\");"); code.add(in + "}"); code.add(in + "catch (ValueException ve)"); code.add(in + "{"); code.add(in + cg.indent(1) + "// Ignore (exception was expected)"); code.add(in + cg.indent(1) + "junk++;"); code.add(in + "}"); return code; } /** * Generate the Java code to check a two operand operator. * @param cg CodeGenerator; the code generator * @param type String; Float, or Double * @param dimensions int; the number of dimensions of the data * @param leftType String; something like Abs, or Rel.Dense * @param rightType String; like leftType * @param resultType String; like leftType * @param operatorName String; something like plus * @param operatorSymbol String; something like + * @return String; Java code for a method that checks the operation */ private static String twoOpChecker(final CodeGenerator cg, final String type, final int dimensions, final String leftType, final String rightType, final String resultType, final String operatorName, final String operatorSymbol) { final String aggregate = 0 == dimensions ? "Scalar" : 1 == dimensions ? "Vector" : "Matrix"; final String suffix = type.startsWith("F") ? "f" : ""; final ArrayList code = new ArrayList(); final String indices = (dimensions > 0 ? "i" : "") + (dimensions > 1 ? ", j" : ""); final String in = cg.indent(dimensions > 0 ? 1 : 0); // If dimensions > 0, all code should be in a try - catch construction if (dimensions > 0) { code.add("try"); code.add("{"); } // Generate the initializers code.add(in + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " leftValue = " + makeInitializer(type, dimensions, "123.4", false) + ";"); code.add(in + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " rightValue = " + makeInitializer(type, dimensions, "234.5", false) + ";"); code.add(in + type + aggregate + "." + leftType + "" + " left = new " + type + aggregate + "." + leftType + "" + "(leftValue, LengthUnit.MILE);"); code.add(in + type + aggregate + "." + rightType + "" + " right = new " + type + aggregate + "." + rightType + "" + "(rightValue, LengthUnit.MILE);"); // Perform the operation code.add(in + "Mutable" + type + aggregate + "." + resultType + " result = " + type + aggregate + "." + operatorName + "(left, right);"); // Check the result if (dimensions > 0) { code.add(in + "for (int i = 0; i < leftValue.length; i++)"); code.add(in + "{"); if (dimensions > 1) { code.add(in + cg.indent(1) + "for (int j = 0; j < leftValue[i].length; j++)"); code.add(in + cg.indent(1) + "{"); } } code.add(in + cg.indent(dimensions) + "assertEquals(\"value of element should be SI " + operatorName + " of contributing elements\", left.getSI(" + indices + ") " + operatorSymbol + " right.getSI(" + indices + "), result.getSI(" + indices + "), 0.001" + suffix + ");"); if (dimensions > 0) { if (dimensions > 1) { code.add(in + cg.indent(1) + "}"); } code.add(in + "}"); code.add("}"); } if (dimensions > 0) { // finish the try - catch construction code.add("catch (ValueException ve)"); code.add("{"); code.add(cg.indent(1) + "fail(\"Caught unexpected ValueException: \" + ve.toString());"); code.add("}"); } return cg.buildMethod( cg.indent(1), "public final|void|binary" + operatorName + "Of" + leftType.replaceAll("\\.", "") + "And" + rightType.replaceAll("\\.", "") + "Test", "Test " + operatorName + "(" + type + aggregate + leftType + ", " + type + aggregate + rightType + ").", null, null, "@SuppressWarnings(\"static-method\")\r\n" + cg.indent(1) + "@Test", CodeGenerator.arrayListToArray(code), false); } /** * Write Java code that creates a call to generate N-dimensional test data. * @param type String; Float, or Double * @param dimensions int; number of dimensions of the data * @param seed String; value of the first element in the test data * @param nonRectangular boolean; generate a non-rectangular array as result * @return String; java code */ private static String makeInitializer(final String type, final int dimensions, final String seed, final boolean nonRectangular) { final String suffix = Character.isDigit(seed.charAt(0)) ? (type.startsWith("F") ? "f" : "") : ""; if (0 == dimensions) { return seed + suffix; } String call = "data"; for (int dimension = 0; dimension < dimensions; dimension++) { call += 0 == dimension ? "(3" : ", " + (dimension + 4); } call += ", " + (dimensions > 1 ? (nonRectangular ? "true" : "false") + ", " : "") + seed + suffix; call += ")"; return call; } /** * Generate Java code for an initializer. * @param cg CodeGenerator * @param dimensions int; number of dimensions of the data * @param type String; Float, or Double * @return String; java code */ private static String generateInitializer(final CodeGenerator cg, final int dimensions, final String type) { if (0 == dimensions) { return ""; } final String firstIndexName = 1 == dimensions ? "index" : "row"; return cg.buildMethod(cg.indent(1), "private static|" + type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + "|data", "Generate test data.", new String[]{ 1 == dimensions ? "final int|size|number of values in the result" : null, 2 == dimensions ? "final int|rows|the number of rows in the result" : null, 2 == dimensions ? "final int|columns|the number of columns in the result" : null, dimensions > 1 ? "final boolean|nonRectangular|if true; return a non-rectangular " + "array; if false; return a rectangular array" : null, "final " + type.toLowerCase() + "|startValue|seed value"}, null, null, new String[]{ type.toLowerCase() + cg.buildEmptyBrackets(dimensions) + " result = new " + type.toLowerCase() + "[" + (1 == dimensions ? "size" : "rows") + "]" + cg.buildEmptyBrackets(dimensions - 1) + ";", dimensions > 1 ? "final int badRowIndex = nonRectangular ? rows - 1 : -1;" : null, "for (int " + firstIndexName + " = 0; " + firstIndexName + " < " + (1 == dimensions ? "size" : "rows") + "; " + firstIndexName + "++)", "{", dimensions > 1 ? cg.indent(1) + "result[row] = new " + type.toLowerCase() + "[row == badRowIndex ? columns + 1 : columns];" : null, dimensions > 1 ? cg.indent(1) + "for (int column = 0; column < result[row].length; column++)" : null, dimensions > 1 ? cg.indent(1) + "{" : null, cg.indent(dimensions) + "result[" + firstIndexName + (dimensions > 1 ? "][column" : "") + "] = " + firstIndexName + (dimensions > 1 ? " * 1000 + column" : "") + " + startValue;", dimensions > 1 ? cg.indent(1) + "}" : null, "}", "return result;"}, false); } }