Thanks for the quick response 1) I will run the mvn checks as suggested and get back to you
2) Yes, I realized the inefficiency and would not work.. I was following up on another alternative but the email got sent prematurely Please ignore my previous email and consider this approach or some variation of it? @FunctionalInterface public interface ComplexFunction { void apply(Complex input, int offset, double[] result); } Example Conjugate implementation public static void conj(Complex in, int offset, double[] result) { result[offset] = in.getReal(); result[offset+1] = in.getImaginary(); } ComplexCartesianImpl data structure will change to double[] realAndImgPair with static factory method as below Complex { static Complex ofCartesian(double[] realAndImgPair); } And the complex functions used like below in Complex and ComplexList Complex { // default implementation are immutable always returning new instance to maintain b/w compatibility default Complex applyFunction(ComplexFunction function) { double[] result = new double[2]; return Complex.ofCartesian(function.apply(this,0,result); } } } ComplexList data structure will change to single double[] realAndImgPair ComplexList { .. private double[] realAndImaginaryPairs; // applies changes in place void forEach(ComplexFunction<Void> fun) { for(int i=0; i < realAndImaginaryPairs.length; i++){ fun.apply(cursor, i,realAndImaginaryPairs); } } Also, all the external list implementations I have reviewed, are using single double[] with real/imag parts interleaved or stored in the first and second half of the array. Thanks Sumanth On Fri, 10 Jun 2022 at 08:31, Alex Herbert <alex.d.herb...@gmail.com> wrote: > Hi, > > Thanks for the design update. I will review and get back to you with more > detailed feedback. Here are some quick thoughts: > > On Fri, 10 Jun 2022 at 12:55, Sumanth Rajkumar <rajkumar.suma...@gmail.com > > > wrote: > > > Hi Alex and Giles, > > > > Thanks for the feedback. > > > > 1) Backward Compatibility and Complex Interface > > Yes. I understand the backward compatibility requirement and my goal is > to > > be fully backward compatible. > > > > Fortunately, the existing Complex class has private constructors and so > it > > is possible to refactor it as an interface. > > I was able to make the change along with a ComplexCartesianImpl class and > > run all unit tests successfully. I did not have to make any changes to > unit > > tests. > > "mvn test" runs successfully on my local machine after the changes > > > > 'mvn test' will not run binary compatibility checks. You should try > building with the default goal: 'mvn'. This will run a binary > compatibility check japicmp:cmp in the 'verify' phase as it requires the > packaged jar file. > > > > > > We could split complex unary operators into two primitive functions ( > > ToDoubleFunction<Complex>) one returning the real part of result and > other > > for imaginary part > > > > interface ComplexFunction { > > ToDoubleFunction<Complex> getReal() ; > > ToDoubleFunction<Complex> getImaginary() ; > > } > > > > > This has concerns for efficiency. Look at some of the more involved > functions and you will see that there will be a lot of repeat computation > if you pass in the same complex number twice. > > And for example the Conjugate implementation would look like this > > ComplexFunction conj = new ComplexFunction2() { > > @Override > > public ToDoubleFunction<Complex> getReal() { > > return complex -> complex.real(); > > } > > @Override > > public ToDoubleFunction<Complex> getImaginary() { > > return complex -> -complex.imag(); > > } > > > > }; > > }; > > > > Quite verbose. However, can you even use a lambda function here? > > > > > > And the functions used like below in Complex and ComplexList > > > > Complex { > > // default implementation are immutable always returning new instance > > to maintain b/w compatibility > > default Complex applyFunction(ComplexFunction function) { > > return > > > > > Complex.ofCartesian(function.getReal().applyAsDouble(this),function.getImaginary().applyAsDouble(this)); > > } > > } > > } > > > > ComplexList { > > .. > > // applies changes in place > > void forEach(ComplexFunction fun) { > > ToDoubleFunction<Complex> realFunc = fun.getReal(); > > ToDoubleFunction<Complex> imgFunc = fun.getImaginary(); > > ComplexCursor cursor = new ComplexCursor(); > > while (cursor.index < r.length) { > > cursor.apply(realFunc.applyAsDouble(cursor), > > imgFunc .applyAsDouble(cursor)); > > cursor.index++; > > } > > } > > ... > > } > > > > Does this make sense or we just stick to the original interface that > > includes ComplexResult<R>? > > > > I think a function for a complex number requires a real and imaginary input > and somewhere to put the real and imaginary answer. How to express this in > an interface that allows chaining is the tricky part. > > Alex >