001package daikon.test;
002
003import static java.util.logging.Level.INFO;
004import static org.junit.Assert.assertEquals;
005
006import daikon.FileIO;
007import daikon.inv.OutputFormat;
008import daikon.inv.ternary.threeScalar.LinearTernaryCore;
009import org.junit.BeforeClass;
010import org.junit.Test;
011
012/** Daikon unit test class. */
013public class LinearTernaryCoreTest {
014
015  /** prepare for tests */
016  @BeforeClass
017  public static void setUpClass() {
018    daikon.LogHelper.setupLogs(INFO);
019    FileIO.new_decl_format = true;
020  }
021
022  void set_cache(LinearTernaryCore ltc, int index, long x, long y, long z) {
023    ltc.def_points[index] = new LinearTernaryCore.Point(x, y, z);
024  }
025
026  void one_test_set_tri_linear(
027      int[][] triples, double goal_a, double goal_b, double goal_c, double goal_d) {
028    @SuppressWarnings("nullness") // testing code: wrapper will never be used
029    LinearTernaryCore ltc = new LinearTernaryCore(null);
030    for (int i = 0; i < triples.length; i++) {
031      assertEquals(3, triples[i].length);
032      set_cache(ltc, i, triples[i][0], triples[i][1], triples[i][2]);
033    }
034    double[] coef;
035    try {
036      coef = ltc.calc_tri_linear(ltc.def_points);
037    } catch (ArithmeticException e) {
038      // In the future, we should perhaps test triples that that don't
039      // determine a plane; but none of the current ones do.
040      throw new Error("Not reached");
041      // throw new Error();
042      // coef = null; // not reached
043    }
044    //  System.out.println("goals: " + goal_a + " " + goal_b + " " + goal_c + " " + goal_d);
045    //  System.out.println("actual: " + coef[0] + " " + coef[1] + " " + coef[2] + " " + coef[3]);
046    // System.out.println("difference: " + (goal_a - ltc.a) + " " + (goal_b - ltc.b) + " " + (goal_c
047    // - ltc.c));
048    assertEquals(goal_a, coef[0], 0);
049    assertEquals(goal_b, coef[1], 0);
050    assertEquals(goal_c, coef[2], 0);
051    assertEquals(goal_d, coef[3], 0);
052  }
053
054  @Test
055  public void test_set_tri_linear() {
056    one_test_set_tri_linear(new int[][] {{1, 2, 1}, {2, 1, 7}, {3, 3, 7}}, 4, -2, -1, 1);
057    one_test_set_tri_linear(
058        new int[][] {{1, 2, 6}, {2, 1, -4}, {3, 3, 7}},
059        //    -3, 7, -1, -5);
060        3,
061        -7,
062        1,
063        5);
064
065    // These have non-integer parameters; must have a LinearTernaryCoreFloat
066    // in order to handle them.
067    //
068    // // a - 3 b + 2 c = -9.5
069    // // 0.5 a + 4 b - 10 c = 9
070    // // 3 a + 0.1 b + 2 c = -2.2
071    // //   solution = -9.5, 9, -2.2
072    // // Restated:
073    // // .5 a - 1.5 b + c = -4.75
074    // // -0.05 a - .4 b + c = -.9
075    // // 1.5 a + 0.05 b + c = -1.1
076    // //   solution = -9.5, 9, -2.2
077    // one_test_set_tri_linear(new float[][] { { .5, -1.5, -4.75 },
078    //                                       { -0.05, -.4, -.9 },
079    //                                       { 1.5, 0.05, -1.1 } },
080    //                         -9.5, 9, -2.2);
081    //
082    // // Another example:
083    // //   2x + 3y + 1/3z = 10
084    // //      3x + 4y + 1z = 17
085    // //      2y + 7z = 46
086    // //
087    // //   Solution:
088    // //   x = 1
089    // //      y = 2
090    // //      z = 6
091  }
092
093  public void one_test_format(double a, double b, double c, double d, String goal_result) {
094    @SuppressWarnings("nullness") // testing code: wrapper will never be used
095    LinearTernaryCore ltc = new LinearTernaryCore(null);
096    ltc.a = a;
097    ltc.b = b;
098    ltc.c = c;
099    ltc.d = d;
100    String actual_result = ltc.format_using(OutputFormat.DAIKON, "x", "y", "z");
101    //    System.out.println("Expecting: " + goal_result);
102    //    System.out.println("Actual:    " + actual_result);
103    assertEquals(goal_result, actual_result);
104  }
105
106  @Test
107  public void test_format() {
108    // Need tests with all combinations of: integer/noninteger, and values
109    // -1,0,1,other.
110    one_test_format(1, 2, 1, 3, "x + 2 * y + z + 3 == 0");
111    one_test_format(-1, 2, 1, 3, "- x + 2 * y + z + 3 == 0");
112    one_test_format(-1, -2, -1, 3, "- x - 2 * y - z + 3 == 0");
113    one_test_format(-1, -2, -4, -3, "- x - 2 * y - 4 * z - 3 == 0");
114    one_test_format(-1, 2, 3, 0, "- x + 2 * y + 3 * z == 0");
115    one_test_format(-1, 0, 0, 3, "- x + 3 == 0");
116    one_test_format(0, -2, 5, -3, "- 2 * y + 5 * z - 3 == 0");
117    one_test_format(-1, 1, -2, 0, "- x + y - 2 * z == 0");
118    one_test_format(-1, -1, 2, 3, "- x - y + 2 * z + 3 == 0");
119    one_test_format(3, -2, 0, -3, "3 * x - 2 * y - 3 == 0");
120    // hmmm, we can't actually have this test because there are never any double coeffs, they're not
121    // calculated as such and are converted to ints
122    //  one_test_format(3.2, -2.2, 1.4, -3.4, "3.2 * x - 2.2 * y + 1.4 * z - 3.4 == 0");
123    one_test_format(3.0, -2.0, 2.0, -3.0, "3 * x - 2 * y + 2 * z - 3 == 0");
124    one_test_format(-1.0, 1.0, 0.0, 0.0, "- x + y == 0");
125  }
126}