Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NUMBERS-186 added additional complex list operations #123

Conversation

sumanth-rajkumar
Copy link
Contributor

This PR introduces additional operations that can be done on ComplexList.

Summary of changes

ComplexListTest - unit tests for complex additional operations on ComplexList
ComplexConsumer - interface that acts as a consumer for the complex element's double real and imaginary parts

@codecov-commenter
Copy link

codecov-commenter commented Sep 6, 2022

Codecov Report

Merging #123 (58e89a4) into complex-gsoc-2022 (2bd5755) will not change coverage.
The diff coverage is n/a.

@@                 Coverage Diff                  @@
##             complex-gsoc-2022     #123   +/-   ##
====================================================
  Coverage                99.13%   99.13%           
  Complexity                1699     1699           
====================================================
  Files                       65       65           
  Lines                     4274     4274           
  Branches                   836      836           
====================================================
  Hits                      4237     4237           
  Misses                      10       10           
  Partials                    27       27           

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

Copy link
Contributor

@aherbert aherbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The forEach has been copied from replaceAll without removing the concurrent modification check or updating the javadoc. The test is also incorrectly named.

For your javadoc can you make sure you do not use the term element; here we should use complex number.

The tests should use data where each item in the list is unique. Index out of bound exceptions should be tested, especially at the upper size limit as without a range check the get methods can return stale/invalid data and the set methods may silently not error and write to an unused part of the backing array.

* @param real Real part \( a \) of the complex number \( (a + ib) \).
* @param imaginary Imaginary part \( b \) of the complex number \( (a + ib) \).
*/
void apply(double real, double imaginary);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

java.util.function.Consumer has the method accept

*/
public double getReal(int index) {
rangeCheck(index);
final int i = index << 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this variable, just perform the index doubling inline

/**
* Gets the real part \( a \) of the complex number \( (a + i b) \) at the indexed position of the list.
*
* @param index Index of the element's real part to get.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Index of the complex number.

@@ -177,6 +203,63 @@ public Complex set(int index, Complex element) {
return oldValue;
}

/**
* Replaces the complex element's real part at the specified position
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change element to number. Element is for a generic list; since this is typed to Complex then all element occurrences should be changed to complex number

/**
* Replaces the complex element's imaginary part at the specified position
* in this list with the specified imaginary element.
* @param index Index of the element's imaginary part to replace.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an empty line

Assertions.assertEquals(list.get(i).getReal(), list.getReal(i));
}
for (int i = 0; i < list.size(); i++) {
Assertions.assertEquals(list.get(i).getImaginary(), list.getImaginary(i));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be placed in the same loop as above. Add a simple message to the assertion, e.g. "real".

list.addAll(list);
list.setReal(2, 200);
list.setImaginary(2, 1);
Assertions.assertEquals(Complex.ofCartesian(200, 1), list.get(2));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test set at all positions:

for (int i = 0; i < list.size(); i++) {
    final double value = Math.PI * i;
    list.setReal(i, value);
    Assertions.assertEquals(value, list.get(i).getReal());
}

Also test set/get with invalid index positions (-1, size, size+1).

@Test
void testToArrayRealAndImaginary() {
ComplexList list = new ComplexList();
list.add(Complex.ofCartesian(42, 13));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a better random list.

list.addAll(list);
list.set(2, Complex.ofCartesian(200, 1));

double[] expectedReal = {42, 42, 200, 42};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double[] expected = list.stream().mapToDouble(Complex::getReal).toArray();


double[] expectedReal = {42, 42, 200, 42};
double[] actualReal = list.toArrayReal();
for (int i = 0; i < expectedReal.length; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Assertions.assertArrayEquals

Copy link
Contributor

@aherbert aherbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks OK. Just a few minor changes to address. Thanks

*/
public void setImaginary(int index, double imaginary) {
rangeCheck(index);
final int i = index << 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index i should be inlined.

*/
public void setReal(int index, double real) {
rangeCheck(index);
final int i = index << 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index i should be inlined.

@@ -152,9 +153,9 @@ void testAddIndexOutOfBoundExceptions() {

@Test
void testRemoveIndexOutOfBoundExceptions() {
List<Complex> objectList = generateList(2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since a lot of the tests now use generateList() then addAll to a new ComplexList instance this should be refactored into a method: private static ComplexList generateComplexList(int)

Copy link
Contributor

@aherbert aherbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you have removed too many uses of i = index << 1. There are some where this is useful.

Also the test class should have generateList and generateComplexList. The later to be used only when the list will not be compared to another list using assertEquals, e.g. for tests for accessor methods.

*/
private static List<Complex> generateList(int size) {
return ThreadLocalRandom.current().doubles(size, -Math.PI, Math.PI)
private static ComplexList generateList(int size) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are use cases for generateList and generateComplexList. The generateList would function as before and return a List implementation from the JDK. This can be assumed to work correctly. The generateComplexList would call generateList and then addAll to a new ComplexList instance. This should be asserted to be equal to the original List. This method can be used for convenience to populate a ComplexList for testing the accessor methods (get/set).

One case where you may wish to have a List that is not a ComplexList is in testing addAll. You also require a non ComplexList for any list compared for equality with ComplexList: you cannot have a list equals comparison to itself as there may be the same error in both implementations being compared.

* @return the complex number.
*/
@Override
public Complex get(int index) {
rangeCheck(index);
final int i = index << 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The precomputed value i will be reused so it can be left as before, please revert.

rangeCheck(index);
final int i = index << 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The precomputed value i will be reused so it can be left as before, please revert.

In addition the call to setNoRangeCheck can be removed. Since you already have the value i this will avoid calling it again.

@aherbert aherbert merged commit ddd2c06 into apache:complex-gsoc-2022 Sep 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants