LMU ☀️ CMSI 2120
DATA STRUCTURES
HOMEWORK #1 Due: 2022-09-15

Learning Objectives

With this assignment you will demonstrate:

Readings and Videos

Please:

Instructions

Work in teams of 1 to 2 students.

Your work will be done in a private GitHub repository called lmu-cmsi-2120 or something similar. Submit to BrightSpace a single text file or pdf that contains the link to this repo. Submit only one submission per team.

Structure your repository, for now, as follows:

  .
  ├── README.md
  └── homework1/
      ├── README.md               (Include ALL students’ names)
      ├── .gitignore
      ├── Quaternion.java         (write this yourself)
      └── QuaternionTest.java     (this is given to you below)  

When grading, I will clone your repository, and run the test program. Since the repo is to be private, please add me as a contributor to your repo (so I can run and comment on your work). My github name is rtoal.

You will be graded on your programming style, so make sure you are set up so that your editor or IDE auto-formats your code. You should also install Sonar Lint because it is amazing. Environment set up was carried out in class earlier, so you should be good already.

Your homework submission will be the state of your repository on the branch master, at 23:59 in the America/Los Angeles time zone on the due date above.

Make sure your README has the names of all the students that have worked on the project.

The Class You Are To Write

The file Quaternion.java should be a Java record with the following:

To best understand the specifics of what each of your constructors and methods must produce, I’ve given you a unit test suite. Use the test suite while you create your class. Building code when a test is already in place is delightful. Make sure to place this test file in your GitHub repo.

QuaternionTest.java
import java.util.List;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class QuaternionTest {

    @Test
    public void testConstructorErrors() {
        // That that NaNs are detected in each argument
        assertThrows(IllegalArgumentException.class,
                () -> new Quaternion(Double.NaN, 0, 0, 0));
        assertThrows(IllegalArgumentException.class,
                () -> new Quaternion(0, Double.NaN, 0, 0));
        assertThrows(IllegalArgumentException.class,
                () -> new Quaternion(0, 0, Double.NaN, 0));
        assertThrows(IllegalArgumentException.class,
                () -> new Quaternion(0, 0, 0, Double.NaN));
    }

    @Test
    public void testAccessors() {
        // Java records give us these for free
        var q = new Quaternion(3.5, 2.25, -100, -1.25);
        assertEquals(3.5, q.a());
        assertEquals(2.25, q.b());
        assertEquals(-100.0, q.c());
        assertEquals(-1.25, q.d());
    }

    @Test
    public void testBasicArithmetic() {
        var q1 = new Quaternion(1, 3, 5, 2);
        var q2 = new Quaternion(-2, 2, 8, -1);
        var q3 = new Quaternion(-1, 5, 13, 1);
        var q4 = new Quaternion(-46, -25, 5, 9);
        assertEquals(q3, q1.plus(q2));
        assertEquals(q1, q3.minus(q2));
        assertEquals(q4, q1.times(q2));
        assertEquals(Quaternion.K, Quaternion.I.times(Quaternion.J));
    }

    @Test
    public void testNorms() {
        var q1 = new Quaternion(60, -20, 9, 12);
        assertEquals(65.0, q1.norm());
        var q2 = new Quaternion(12, 3, 84, -4);
        assertEquals(85.0, q2.norm());
        var q3 = new Quaternion(1, -1, -1, 1);
        var q4 = new Quaternion(0.5, -0.5, -0.5, 0.5);
        assertEquals(q4, q3.normalized());
    }

    @Test
    public void testConjugates() {
        var q1 = new Quaternion(1, -21, -1, 13);
        var q2 = new Quaternion(1, 21, 1, -13);
        assertEquals(q2, q1.conjugate());
    }

    @Test
    public void testInverses() {
        var q1 = new Quaternion(1, -1, 1, -1);
        var q2 = new Quaternion(0.25, 0.25, -0.25, 0.25);
        assertEquals(q2, q1.inverse());
        assertEquals(q1, q2.inverse());
    }

    @Test
    public void testCoefficients() {
        assertEquals(List.of(0.0, 0.0, 0.0, 0.0),
                new Quaternion(0, 0, 0, 0).coefficients());
        assertEquals(List.of(2.0, 1.5, 10.0, -8.0),
                new Quaternion(2, 1.5, 10, -8).coefficients());
    }

    @Test
    public void testToString() {
        assertEquals("Quaternion[a=0.0, b=0.0, c=0.0, d=0.0]",
                new Quaternion(0, 0, 0, 0).toString());
        assertEquals("Quaternion[a=0.0, b=-1.0, c=0.0, d=2.25]",
                new Quaternion(0, -1, 0, 2.25).toString());
        assertEquals("Quaternion[a=0.0, b=0.0, c=0.0, d=-1.0]",
                Quaternion.ZERO.minus(Quaternion.K).toString());
    }
}

Grading

The following elements will all contribute to your grade:

In addition, I will be scoring code quality, which is sometimes subjective to be sure, but you deserve feedback.