Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-08-03 Thread Sumanth Rajkumar
Hi,

I have made a preliminary complex list implementation class which is backed
by a single double array in interleaved format.
I made some test cases for the forEach methods as well.
This can be viewed here [1]. Please let me know what you think and if I'm
on the right track.

Thanks,

Sumanth

[1]
https://github.com/sumanth-rajkumar/commons-numbers/tree/NUMBERS-186.complex_list_support/commons-numbers-complex/src

On Tue, 2 Aug 2022 at 13:26, Sumanth Rajkumar 
wrote:

> Thanks Alex for the feedback,
>
> I'll work on a ComplexList class that implements the List interface and is
> backed by a single double array in interleaved format.
> I'll have something ready to look at by tomorrow.
>
> Thanks,
>
> Sumanth
>
> On Tue, 2 Aug 2022 at 03:52, Alex Herbert 
> wrote:
>
>> On Mon, 1 Aug 2022 at 17:38, Sumanth Rajkumar > >
>> wrote:
>>
>> > Hi,
>> >
>> > > I think that Alex's suggestion still holds: Better focus on one
>> > > task at a time.  Are the "list" and "matrix" features related?
>> >
>> > OK, Will focus on list features first and focus on extending all
>> existing
>> > methods on the Complex class to Lists.
>> >
>> > UnaryOperators will apply the operation (using refactored static
>> methods)
>> > to each element.
>> > BinaryOperators for lists will have two variants.
>> > For the first variant, the second operand is a single complex number
>> that
>> > is applied as second operand for all elements on List
>> > The second variant operates on two Lists. Can we look at this later?
>> >
>>
>> For an operand that is a single complex number then this should be
>> satisfied by passing a lambda function to the unary forEach. The same
>> would
>> be the same for a single double factor. So these seem redundant and can be
>> covered by documentation.
>>
>> I would suggest you create a List implementation that only
>> satisfies the list interface in an optimal manner. If you extend
>> java.util.AbstractList the minimal implementation is often not optimal for
>> the storage (for example the spliterator and the forEach constructs).
>>
>> The support for a JDK Collection may not have to add any additional
>> methods
>> for processing. It would merely replace using ArrayList.
>> Numerical
>> processing of complex numbers could be added instead to a more focussed
>> data structure that does not support the entire Collection API, i.e. the
>> vector and matrix concepts previously proposed.
>>
>>
>> >
>> > > Do we have one use case for the "list" feature?
>> > > I see there a lot factory methods that seem to defeat the
>> > > intended purpose (AFAIU Matt's remark) of letting the caller
>> > > decide on the input format.
>> > > Similarly, the "parse" feature should be left to the code that
>> > > handles the input.  IOW shouldn't we separate the concerns
>> > > of converting the input (array, stream, list of strings, ...) from
>> > > what can be done with a "list" instance?
>> >
>> > Since the lists can have different underlying data storage
>> implementations
>> > such as
>> >  a) single double primitive array or DoubleBuffer in interleaved format
>> >  b) single double primitive array or DoubleBuffer in sub array format
>> >  c) separate arrays/DoubleBuffers for real and imaginary parts
>> >
>> > Based on earlier discussions, Alex wanted the iteration logic over the
>> list
>> > to apply the operators to be within the List implementation
>> > So each implementation will have its own implementation of operators
>> that
>> > is optimal for its data storage
>> >
>> > For now, should we focus on more than 1 implementation? If it is just 1
>> > implementation, which one can I pick up first?
>> >
>>
>> 1 implementation is the best start point to build the API.
>>
>>
>> > Should we have a common interface (minimum methods/operations that all
>> > implementations should support)?
>> >
>>
>> That makes sense. However a known backing format for the data will allow
>> optimal computation. So once the API is established for a single data
>> structure format we can test speed of computation when mixing backing data
>> structures.
>>
>>
>> >
>> > If so, I can first focus on finalizing the List interface and then look
>> at
>> > implementations
>> >
>> > I was also looking at the EJML api's [1].
>> > They support three API styles a) Procedural b) SimpleMatrix and c)
>> > Equations (Matlab style)
>> >
>> > It looks like we will be implementing the SimpleMatrix style. Should we
>> > also consider other approaches?
>> >
>>
>> Equations requires parsing text input. I would put that out-of-scope. I
>> would say an OO style is the most natural from a Java perspective. The API
>> could be similar to the matrix functionality in Commons Math.
>>
>> Alex
>>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-08-02 Thread Sumanth Rajkumar
Thanks Alex for the feedback,

I'll work on a ComplexList class that implements the List interface and is
backed by a single double array in interleaved format.
I'll have something ready to look at by tomorrow.

Thanks,

Sumanth

On Tue, 2 Aug 2022 at 03:52, Alex Herbert  wrote:

> On Mon, 1 Aug 2022 at 17:38, Sumanth Rajkumar 
> wrote:
>
> > Hi,
> >
> > > I think that Alex's suggestion still holds: Better focus on one
> > > task at a time.  Are the "list" and "matrix" features related?
> >
> > OK, Will focus on list features first and focus on extending all existing
> > methods on the Complex class to Lists.
> >
> > UnaryOperators will apply the operation (using refactored static methods)
> > to each element.
> > BinaryOperators for lists will have two variants.
> > For the first variant, the second operand is a single complex number that
> > is applied as second operand for all elements on List
> > The second variant operates on two Lists. Can we look at this later?
> >
>
> For an operand that is a single complex number then this should be
> satisfied by passing a lambda function to the unary forEach. The same would
> be the same for a single double factor. So these seem redundant and can be
> covered by documentation.
>
> I would suggest you create a List implementation that only
> satisfies the list interface in an optimal manner. If you extend
> java.util.AbstractList the minimal implementation is often not optimal for
> the storage (for example the spliterator and the forEach constructs).
>
> The support for a JDK Collection may not have to add any additional methods
> for processing. It would merely replace using ArrayList. Numerical
> processing of complex numbers could be added instead to a more focussed
> data structure that does not support the entire Collection API, i.e. the
> vector and matrix concepts previously proposed.
>
>
> >
> > > Do we have one use case for the "list" feature?
> > > I see there a lot factory methods that seem to defeat the
> > > intended purpose (AFAIU Matt's remark) of letting the caller
> > > decide on the input format.
> > > Similarly, the "parse" feature should be left to the code that
> > > handles the input.  IOW shouldn't we separate the concerns
> > > of converting the input (array, stream, list of strings, ...) from
> > > what can be done with a "list" instance?
> >
> > Since the lists can have different underlying data storage
> implementations
> > such as
> >  a) single double primitive array or DoubleBuffer in interleaved format
> >  b) single double primitive array or DoubleBuffer in sub array format
> >  c) separate arrays/DoubleBuffers for real and imaginary parts
> >
> > Based on earlier discussions, Alex wanted the iteration logic over the
> list
> > to apply the operators to be within the List implementation
> > So each implementation will have its own implementation of operators that
> > is optimal for its data storage
> >
> > For now, should we focus on more than 1 implementation? If it is just 1
> > implementation, which one can I pick up first?
> >
>
> 1 implementation is the best start point to build the API.
>
>
> > Should we have a common interface (minimum methods/operations that all
> > implementations should support)?
> >
>
> That makes sense. However a known backing format for the data will allow
> optimal computation. So once the API is established for a single data
> structure format we can test speed of computation when mixing backing data
> structures.
>
>
> >
> > If so, I can first focus on finalizing the List interface and then look
> at
> > implementations
> >
> > I was also looking at the EJML api's [1].
> > They support three API styles a) Procedural b) SimpleMatrix and c)
> > Equations (Matlab style)
> >
> > It looks like we will be implementing the SimpleMatrix style. Should we
> > also consider other approaches?
> >
>
> Equations requires parsing text input. I would put that out-of-scope. I
> would say an OO style is the most natural from a Java perspective. The API
> could be similar to the matrix functionality in Commons Math.
>
> Alex
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-08-02 Thread Alex Herbert
On Mon, 1 Aug 2022 at 17:38, Sumanth Rajkumar 
wrote:

> Hi,
>
> > I think that Alex's suggestion still holds: Better focus on one
> > task at a time.  Are the "list" and "matrix" features related?
>
> OK, Will focus on list features first and focus on extending all existing
> methods on the Complex class to Lists.
>
> UnaryOperators will apply the operation (using refactored static methods)
> to each element.
> BinaryOperators for lists will have two variants.
> For the first variant, the second operand is a single complex number that
> is applied as second operand for all elements on List
> The second variant operates on two Lists. Can we look at this later?
>

For an operand that is a single complex number then this should be
satisfied by passing a lambda function to the unary forEach. The same would
be the same for a single double factor. So these seem redundant and can be
covered by documentation.

I would suggest you create a List implementation that only
satisfies the list interface in an optimal manner. If you extend
java.util.AbstractList the minimal implementation is often not optimal for
the storage (for example the spliterator and the forEach constructs).

The support for a JDK Collection may not have to add any additional methods
for processing. It would merely replace using ArrayList. Numerical
processing of complex numbers could be added instead to a more focussed
data structure that does not support the entire Collection API, i.e. the
vector and matrix concepts previously proposed.


>
> > Do we have one use case for the "list" feature?
> > I see there a lot factory methods that seem to defeat the
> > intended purpose (AFAIU Matt's remark) of letting the caller
> > decide on the input format.
> > Similarly, the "parse" feature should be left to the code that
> > handles the input.  IOW shouldn't we separate the concerns
> > of converting the input (array, stream, list of strings, ...) from
> > what can be done with a "list" instance?
>
> Since the lists can have different underlying data storage implementations
> such as
>  a) single double primitive array or DoubleBuffer in interleaved format
>  b) single double primitive array or DoubleBuffer in sub array format
>  c) separate arrays/DoubleBuffers for real and imaginary parts
>
> Based on earlier discussions, Alex wanted the iteration logic over the list
> to apply the operators to be within the List implementation
> So each implementation will have its own implementation of operators that
> is optimal for its data storage
>
> For now, should we focus on more than 1 implementation? If it is just 1
> implementation, which one can I pick up first?
>

1 implementation is the best start point to build the API.


> Should we have a common interface (minimum methods/operations that all
> implementations should support)?
>

That makes sense. However a known backing format for the data will allow
optimal computation. So once the API is established for a single data
structure format we can test speed of computation when mixing backing data
structures.


>
> If so, I can first focus on finalizing the List interface and then look at
> implementations
>
> I was also looking at the EJML api's [1].
> They support three API styles a) Procedural b) SimpleMatrix and c)
> Equations (Matlab style)
>
> It looks like we will be implementing the SimpleMatrix style. Should we
> also consider other approaches?
>

Equations requires parsing text input. I would put that out-of-scope. I
would say an OO style is the most natural from a Java perspective. The API
could be similar to the matrix functionality in Commons Math.

Alex


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-08-01 Thread Sumanth Rajkumar
Hi,

> I think that Alex's suggestion still holds: Better focus on one
> task at a time.  Are the "list" and "matrix" features related?

OK, Will focus on list features first and focus on extending all existing
methods on the Complex class to Lists.

UnaryOperators will apply the operation (using refactored static methods)
to each element.
BinaryOperators for lists will have two variants.
For the first variant, the second operand is a single complex number that
is applied as second operand for all elements on List
The second variant operates on two Lists. Can we look at this later?

> Do we have one use case for the "list" feature?
> I see there a lot factory methods that seem to defeat the
> intended purpose (AFAIU Matt's remark) of letting the caller
> decide on the input format.
> Similarly, the "parse" feature should be left to the code that
> handles the input.  IOW shouldn't we separate the concerns
> of converting the input (array, stream, list of strings, ...) from
> what can be done with a "list" instance?

Since the lists can have different underlying data storage implementations
such as
 a) single double primitive array or DoubleBuffer in interleaved format
 b) single double primitive array or DoubleBuffer in sub array format
 c) separate arrays/DoubleBuffers for real and imaginary parts

Based on earlier discussions, Alex wanted the iteration logic over the list
to apply the operators to be within the List implementation
So each implementation will have its own implementation of operators that
is optimal for its data storage

For now, should we focus on more than 1 implementation? If it is just 1
implementation, which one can I pick up first?

Should we have a common interface (minimum methods/operations that all
implementations should support)?

If so, I can first focus on finalizing the List interface and then look at
implementations

I was also looking at the EJML api's [1].
They support three API styles a) Procedural b) SimpleMatrix and c)
Equations (Matlab style)

It looks like we will be implementing the SimpleMatrix style. Should we
also consider other approaches?

Thanks,

Sumanth

[1]
http://ejml.org/wiki/index.php?title=Main_Page#:~:text=EJML%20has%20three,of%20writing%20equations

On Fri, 29 Jul 2022 at 10:41, Gilles Sadowski  wrote:

> Hello.
>
> Le jeu. 28 juil. 2022 à 22:28, Sumanth Rajkumar
>  a écrit :
> >
> > Hi,
> >
> > I've completed the task of refactoring all complex operations to static
> > functions and it has been merged to the complex-gsoc-2022 branch. Thank
> you
> > for all the help to make this happen.
> >
> > I wanted to talk about the next task and get some inputs from all of you
> on
> > how to start.
> >
> > Now, I'm going to be working on complex list and matrix support. I have
> > already begun working on this which can be seen in my github branch [1].
> >
> > Right now, my work is based on the idea of a mutable list representation
> of
> > a set of complex numbers (List) using a backing double[] for
> > storage.
> >
> > I know Matt mentioned using Buffers as well and so I was hoping if you
> can
> > give a little more detail about this. If there are any other suggestions,
> > please let me know.
> >
> > Thanks,
> >
> > Sumanth
> >
> > [1]
> >
> https://github.com/sumanth-rajkumar/commons-numbers/tree/NUMBERS-186.complex_list_and_matrix_support
>
> I think that Alex's suggestion still holds: Better focus on one
> task at a time.  Are the "list" and "matrix" features related?
>
> Do we have one use case for the "list" feature?
> I see there a lot factory methods that seem to defeat the
> intended purpose (AFAIU Matt's remark) of letting the caller
> decide on the input format.
> Similarly, the "parse" feature should be left to the code that
> handles the input.  IOW shouldn't we separate the concerns
> of converting the input (array, stream, list of strings, ...) from
> what can be done with a "list" instance?
>
> Do we target linear algebra for complex numbers?
> What use-cases for the "ComplexMatrix" and "ComplexVector"
> interfaces?
>
> Regards,
> Gilles
>
> -
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-29 Thread Gilles Sadowski
Hello.

Le jeu. 28 juil. 2022 à 22:28, Sumanth Rajkumar
 a écrit :
>
> Hi,
>
> I've completed the task of refactoring all complex operations to static
> functions and it has been merged to the complex-gsoc-2022 branch. Thank you
> for all the help to make this happen.
>
> I wanted to talk about the next task and get some inputs from all of you on
> how to start.
>
> Now, I'm going to be working on complex list and matrix support. I have
> already begun working on this which can be seen in my github branch [1].
>
> Right now, my work is based on the idea of a mutable list representation of
> a set of complex numbers (List) using a backing double[] for
> storage.
>
> I know Matt mentioned using Buffers as well and so I was hoping if you can
> give a little more detail about this. If there are any other suggestions,
> please let me know.
>
> Thanks,
>
> Sumanth
>
> [1]
> https://github.com/sumanth-rajkumar/commons-numbers/tree/NUMBERS-186.complex_list_and_matrix_support

I think that Alex's suggestion still holds: Better focus on one
task at a time.  Are the "list" and "matrix" features related?

Do we have one use case for the "list" feature?
I see there a lot factory methods that seem to defeat the
intended purpose (AFAIU Matt's remark) of letting the caller
decide on the input format.
Similarly, the "parse" feature should be left to the code that
handles the input.  IOW shouldn't we separate the concerns
of converting the input (array, stream, list of strings, ...) from
what can be done with a "list" instance?

Do we target linear algebra for complex numbers?
What use-cases for the "ComplexMatrix" and "ComplexVector"
interfaces?

Regards,
Gilles

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-28 Thread Sumanth Rajkumar
Hi,

I've completed the task of refactoring all complex operations to static
functions and it has been merged to the complex-gsoc-2022 branch. Thank you
for all the help to make this happen.

I wanted to talk about the next task and get some inputs from all of you on
how to start.

Now, I'm going to be working on complex list and matrix support. I have
already begun working on this which can be seen in my github branch [1].

Right now, my work is based on the idea of a mutable list representation of
a set of complex numbers (List) using a backing double[] for
storage.

I know Matt mentioned using Buffers as well and so I was hoping if you can
give a little more detail about this. If there are any other suggestions,
please let me know.

Thanks,

Sumanth

[1]
https://github.com/sumanth-rajkumar/commons-numbers/tree/NUMBERS-186.complex_list_and_matrix_support


On Tue, 12 Jul 2022 at 10:03, Sumanth Rajkumar 
wrote:

> Hi,
>
> I committed my changes to the test classes into the opened PR and I think
> it ran the checks by itself without needing your approval.
>
> Please let me know if there's anything else I need to change.
>
> Thanks,
>
> Sumanth
>
> On Mon, Jul 11, 2022, 7:45 PM Alex Herbert 
> wrote:
>
>> On Mon, 11 Jul 2022 at 22:56, Gilles Sadowski 
>> wrote:
>>
>> > Le lun. 11 juil. 2022 à 20:03, Sumanth Rajkumar
>> >  a écrit :
>> > >
>> > > Hi,
>> > >
>> > > I have finished updating the test classes, but I am encountering a
>> > problem
>> > > in the ComplexEdgeCaseTest class.
>> > >
>> > > private static void assertComplex(double a, double b,
>> > >   String name,
>> UnaryOperator
>> > > operation,
>> > >
>>  ComplexUnaryOperator
>> > > operation2,
>> > >   double x, double y, long
>> maxUlps) {
>> > > }
>> > >
>> > >
>> > > I added my ComplexUnaryOperator as a parameter and am getting the
>> error
>> > of
>> > > having more than 7 parameters in this method.
>> > > Is there anything I can do?
>> >
>> > Assuming that the error is raised by "CheckStyle" (?), this check can
>> > be disabled
>> > on a class by class basis in this configuration file:
>> >   src/main/resources/checkstyle/checkstyle-suppressions.xml
>> >
>>
>> It may be a PMD error too [1]. The PMD error can be suppressed using the
>> file:
>>
>> src/main/resources/pmd/pmd-ruleset.xml
>>
>> However in Numbers there is a checkstyle suppression for ParameterNumber
>> but no suppressions for PMD for ExcessiveParameterList, so you may not
>> need
>> this.
>>
>> Alex
>>
>> [1]
>>
>> https://pmd.github.io/latest/pmd_rules_apex_design.html#excessiveparameterlist
>>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-12 Thread Sumanth Rajkumar
Hi,

I committed my changes to the test classes into the opened PR and I think
it ran the checks by itself without needing your approval.

Please let me know if there's anything else I need to change.

Thanks,

Sumanth

On Mon, Jul 11, 2022, 7:45 PM Alex Herbert  wrote:

> On Mon, 11 Jul 2022 at 22:56, Gilles Sadowski 
> wrote:
>
> > Le lun. 11 juil. 2022 à 20:03, Sumanth Rajkumar
> >  a écrit :
> > >
> > > Hi,
> > >
> > > I have finished updating the test classes, but I am encountering a
> > problem
> > > in the ComplexEdgeCaseTest class.
> > >
> > > private static void assertComplex(double a, double b,
> > >   String name,
> UnaryOperator
> > > operation,
> > >
>  ComplexUnaryOperator
> > > operation2,
> > >   double x, double y, long
> maxUlps) {
> > > }
> > >
> > >
> > > I added my ComplexUnaryOperator as a parameter and am getting the error
> > of
> > > having more than 7 parameters in this method.
> > > Is there anything I can do?
> >
> > Assuming that the error is raised by "CheckStyle" (?), this check can
> > be disabled
> > on a class by class basis in this configuration file:
> >   src/main/resources/checkstyle/checkstyle-suppressions.xml
> >
>
> It may be a PMD error too [1]. The PMD error can be suppressed using the
> file:
>
> src/main/resources/pmd/pmd-ruleset.xml
>
> However in Numbers there is a checkstyle suppression for ParameterNumber
> but no suppressions for PMD for ExcessiveParameterList, so you may not need
> this.
>
> Alex
>
> [1]
>
> https://pmd.github.io/latest/pmd_rules_apex_design.html#excessiveparameterlist
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-11 Thread Alex Herbert
On Mon, 11 Jul 2022 at 22:56, Gilles Sadowski  wrote:

> Le lun. 11 juil. 2022 à 20:03, Sumanth Rajkumar
>  a écrit :
> >
> > Hi,
> >
> > I have finished updating the test classes, but I am encountering a
> problem
> > in the ComplexEdgeCaseTest class.
> >
> > private static void assertComplex(double a, double b,
> >   String name, UnaryOperator
> > operation,
> >   ComplexUnaryOperator
> > operation2,
> >   double x, double y, long maxUlps) {
> > }
> >
> >
> > I added my ComplexUnaryOperator as a parameter and am getting the error
> of
> > having more than 7 parameters in this method.
> > Is there anything I can do?
>
> Assuming that the error is raised by "CheckStyle" (?), this check can
> be disabled
> on a class by class basis in this configuration file:
>   src/main/resources/checkstyle/checkstyle-suppressions.xml
>

It may be a PMD error too [1]. The PMD error can be suppressed using the
file:

src/main/resources/pmd/pmd-ruleset.xml

However in Numbers there is a checkstyle suppression for ParameterNumber
but no suppressions for PMD for ExcessiveParameterList, so you may not need
this.

Alex

[1]
https://pmd.github.io/latest/pmd_rules_apex_design.html#excessiveparameterlist


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-11 Thread Gilles Sadowski
Le lun. 11 juil. 2022 à 20:03, Sumanth Rajkumar
 a écrit :
>
> Hi,
>
> I have finished updating the test classes, but I am encountering a problem
> in the ComplexEdgeCaseTest class.
>
> private static void assertComplex(double a, double b,
>   String name, UnaryOperator
> operation,
>   ComplexUnaryOperator
> operation2,
>   double x, double y, long maxUlps) {
> }
>
>
> I added my ComplexUnaryOperator as a parameter and am getting the error of
> having more than 7 parameters in this method.
> Is there anything I can do?

Assuming that the error is raised by "CheckStyle" (?), this check can
be disabled
on a class by class basis in this configuration file:
  src/main/resources/checkstyle/checkstyle-suppressions.xml

Regards,
Gilles

> > [...]

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-11 Thread Sumanth Rajkumar
Hi,

I have finished updating the test classes, but I am encountering a problem
in the ComplexEdgeCaseTest class.

private static void assertComplex(double a, double b,
  String name, UnaryOperator
operation,
  ComplexUnaryOperator
operation2,
  double x, double y, long maxUlps) {
}


I added my ComplexUnaryOperator as a parameter and am getting the error of
having more than 7 parameters in this method.
Is there anything I can do?

Thanks,

Sumanth


On Tue, 5 Jul 2022 at 15:50, Sumanth Rajkumar 
wrote:

> Thanks for the feedback Alex,
>
> > Not a problem. Just write a dedicated method for Complex and a generic
> > method in ComplexFunctions. This small level of code duplication is
> > acceptable where the efficiency of the method is greatly improved by
> > rewriting it, as has been done for the scalar functions.
>
> For proj(), I had to take it out of ComplexFunctions for now to pass the
> coverage checks,
> but I have left the original code for proj() in the Complex class.
>
> > Why should I have to return a ComplexDouble? Since the ComplexConstructor
> > is typed it makes more sense to have the methods that use it to also be
> > typed. These methods should perform an operation that generates a real
> and
> > imaginary part. This is passed to the provided constructor. It should be
> up
> > to the provider of the constructor (i.e. the caller) to decide what to do
> > with the result. By typing to ComplexDouble you are removing that
> > flexibility.
>
> > However there is no requirement to specify what R is, allowing it to be
> > Void. This also decouples the interface from Complex and ComplexDouble.
> > Note that this may make ComplexDouble obsolete which would simplify the
> > current changes.
>
> > I've not applied this change to your entire current diff so there may be
> > some issues, for example with the scalar functions. I am interested to
> see
> > if this would work.
>
> So, I have made all interfaces typed and updated the method signatures
> accordingly.
> Please let me know if there are any problems with these changes.
>
> As for updating the test suite, I am currently working on that right now
> and will let you know as soon as I am done.
>
> Thanks,
>
> Sumanth
>
>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-05 Thread Sumanth Rajkumar
Thanks for the feedback Alex,

> Not a problem. Just write a dedicated method for Complex and a generic
> method in ComplexFunctions. This small level of code duplication is
> acceptable where the efficiency of the method is greatly improved by
> rewriting it, as has been done for the scalar functions.

For proj(), I had to take it out of ComplexFunctions for now to pass the
coverage checks,
but I have left the original code for proj() in the Complex class.

> Why should I have to return a ComplexDouble? Since the ComplexConstructor
> is typed it makes more sense to have the methods that use it to also be
> typed. These methods should perform an operation that generates a real and
> imaginary part. This is passed to the provided constructor. It should be
up
> to the provider of the constructor (i.e. the caller) to decide what to do
> with the result. By typing to ComplexDouble you are removing that
> flexibility.

> However there is no requirement to specify what R is, allowing it to be
> Void. This also decouples the interface from Complex and ComplexDouble.
> Note that this may make ComplexDouble obsolete which would simplify the
> current changes.

> I've not applied this change to your entire current diff so there may be
> some issues, for example with the scalar functions. I am interested to see
> if this would work.

So, I have made all interfaces typed and updated the method signatures
accordingly.
Please let me know if there are any problems with these changes.

As for updating the test suite, I am currently working on that right now
and will let you know as soon as I am done.

Thanks,

Sumanth


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-05 Thread Alex Herbert
On Mon, 4 Jul 2022 at 23:00, Sumanth Rajkumar 
wrote:

> Thanks Alex for PR feedback.
> I have incorporated the majority of the requested changes to the PR.
>
> I would like to discuss the remaining points here.
>
> > In
>
> commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java:
> > Note that by making this a default that creates an instance of Complex
> you impose memory allocation overhead to any call site that just has the
> real and imaginary parts (e.g. a structure storing a list of complex
> numbers using primitive arrays).
> > The ComplexDouble apply(ComplexDouble in,
> ComplexConstructor out) method should be a default that
> calls this function using the real and imaginary parts.
>
> The existing unit test for Complex Projection (proj) is expecting the
> returned result to be the same as the passed input Complex instance except
> for the isInfinite edge case.
> This was the main reason for making the functional interface accept a
> ComplexDouble instead of primitive real and imaginary parts.
>

Passing an existing unit test should not govern a design decision.

The proj method will return the same number if it is not an infinite
complex number. That is all that is required to pass the test, the input
and output should have the exact same real and imaginary parts. Note that
the Complex class is immutable so it can return itself. The test for object
identity can be dropped in a generic case where the output is passed to the
ComplexConstructor.


>
> The additional memory allocation for the input can be eliminated (for the
> example of primitive array backed lists), by combining it with the
> constructed result object.
> We had decided to incur the overhead for the complex Constructor
> result object in the context of functional compositions and thread safety
> discussion before.
> So, passing in a cursor iterator item (that captures the index) as both
> ComplexDouble input and ComplexResult constructor should avoid any
> additional overhead?
>

In this case yes. But in the case of usage outside of the complex package,
for example if the raw real and imaginary arrays are created by a 2D FFT.

At present I do not see a downside to the functional method being the
separate arguments of real and imaginary primitives, other than it
decouples the values and so is not encapsulated. Let's see what others
think.


>
> If we decide to use primitive types for the functional interface, then we
> cannot use it for the projection method.
>

Not a problem. Just write a dedicated method for Complex and a generic
method in ComplexFunctions. This small level of code duplication is
acceptable where the efficiency of the method is greatly improved by
rewriting it, as has been done for the scalar functions.


>
>
> > @FunctionalInterface
> >  public interface ComplexScalarFunction {
> >
> > ComplexDouble apply(ComplexDouble c, double f,
> ComplexConstructor result);
> >
> > }
> > This interface should be typed: the result is accepted by the
> ComplexConstructor and this can be typed.
>
>
> By typed, did you mean to make this a generic interface
> ComplexScalarFunction
> ?
> ComplexUnaryOperator and ComplexBinaryOperator are not generic and
> constrained to ComplexDouble types
>

Why should I have to return a ComplexDouble? Since the ComplexConstructor
is typed it makes more sense to have the methods that use it to also be
typed. These methods should perform an operation that generates a real and
imaginary part. This is passed to the provided constructor. It should be up
to the provider of the constructor (i.e. the caller) to decide what to do
with the result. By typing to ComplexDouble you are removing that
flexibility.

ComplexUnaryOperator extends UnaryOperator

I do not see what extending UnaryOperator provides. It constrains the
interface to having to support composition imposed by Function. Note
that composition can avoid the Complex constructor by directly chaining the
output to the next input. Consider this simplification:

public interface ComplexUnaryOperator {
R apply(double r, double i, ComplexConstructor out);

default ComplexUnaryOperator andThen(ComplexUnaryOperator after) {
Objects.requireNonNull(after);
return (r, i, out) -> apply(r, i, (x, y) -> after.apply(x, y, out));
}
}

public interface ComplexBinaryOperator {
R apply(double r1, double i1, double r2, double i2,
ComplexConstructor out);

default ComplexBinaryOperator andThen(ComplexUnaryOperator after)
{
Objects.requireNonNull(after);
return (r1, i1, r2, i2, out) -> apply(r1, i1, r2, i2, (x, y) ->
after.apply(x, y, out));
}
}

Note that this has some differences from java.util.function during
composition.

In the generic case of java.util.function an object is returned. This is
passed to the next function and may be changed to an object of a different
type. So a composition of Function and Function becomes
Function (via T -> R -> V).

In the complex 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-07-04 Thread Sumanth Rajkumar
Thanks Alex for PR feedback.
I have incorporated the majority of the requested changes to the PR.

I would like to discuss the remaining points here.

> In
commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexUnaryOperator.java:
> Note that by making this a default that creates an instance of Complex
you impose memory allocation overhead to any call site that just has the
real and imaginary parts (e.g. a structure storing a list of complex
numbers using primitive arrays).
> The ComplexDouble apply(ComplexDouble in,
ComplexConstructor out) method should be a default that
calls this function using the real and imaginary parts.

The existing unit test for Complex Projection (proj) is expecting the
returned result to be the same as the passed input Complex instance except
for the isInfinite edge case.
This was the main reason for making the functional interface accept a
ComplexDouble instead of primitive real and imaginary parts.

The additional memory allocation for the input can be eliminated (for the
example of primitive array backed lists), by combining it with the
constructed result object.
We had decided to incur the overhead for the complex Constructor
result object in the context of functional compositions and thread safety
discussion before.
So, passing in a cursor iterator item (that captures the index) as both
ComplexDouble input and ComplexResult constructor should avoid any
additional overhead?

If we decide to use primitive types for the functional interface, then we
cannot use it for the projection method.


> @FunctionalInterface
>  public interface ComplexScalarFunction {
>
> ComplexDouble apply(ComplexDouble c, double f,
ComplexConstructor result);
>
> }
> This interface should be typed: the result is accepted by the
ComplexConstructor and this can be typed.


By typed, did you mean to make this a generic interface
ComplexScalarFunction
?
ComplexUnaryOperator and ComplexBinaryOperator are not generic and
constrained to ComplexDouble types


> It may be wise to update the test suite to ensure that all tests
currently applied to Complex are applied to ComplexFunctions using a
ComplexConstructor other than Complex, for example using a dummy
implementation:
>
> class ComplexNumber implements ComplexConstructor {
>// (r, i) members
>
>@Override
>public ComplexNumber apply(double r, double i) {
>// store (r, i) ...
>return this;
>}
> }
>
>This will detect the edge cases all pass through to the input constructor
to create the result. The test should assert the ComplexConstructor
received the expected values.

For now, shall I copy all the tests from the CStandardTest, CReferenceTest
and ComplexEdgeCaseTest to ComplexFunctionsTest and modify it to use a
dummy constructor?
Also please note as mentioned above for the complex.proj method, currently
we are not invoking the complex constructor for normal cases.


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-27 Thread Gilles Sadowski
Hello.

> > [...]
> > I have raised PR #113 after rebasing to the master branch with Alex's
> > checkstyle changes
> >
> > As per feedback, I have made the following changes
> > a) Added javadoc comments
> > b) Ensured test coverage
> > c) Renamed accessors on the interface
> >
>
> [...]
>
> >
> >
> > > In "DComplex", I propose that the accessors be named "real()" and
> > > "imag()" (or just
> > > "re()" and "im()").  ["DComplex" is not a very satisfying name either...]
> >
> > For the interface name, shall I change it to Complex64 from DComplex?
> >
>
> In c the 'complex' keyword is a suffix:
>
> double complex c1;
> float complex c2;
> long double complex c3;
>
> In c++ the type is generic (and read as a suffix):
>
> complex c1;
> complex c2;
>
> Either of these would be my preference over DComplex or Complex64.

Just to be sure: Are we discussing this because "Complex" is
already taken?

> > > Are we sure that all this code needs to be part of the public API?
> > > If not, I'd suggest limiting accessibility to "package-private".
> >
> > Are you referring to the static methods in ComplexFunctions and
> > ComplexBiFunctions classes?
> > I think they would need to be public for developers to be able to compose
> > multiple operations...
> >
>
> The static helper functions have been extracted to support all the ISO c99
> operations on the list structure of complex numbers.
>
> A list will ideally implement a generic foreach operation. So to apply a
> single function only requires making the static functions public. The
> alternative is to make the list expose all the ISO c99 operations in its
> public API.
>
> To create a composite function that eventually writes back to the list can
> be implemented by writing intermediate values to a result which is then
> passed to the next operation. This can be satisfied by using the Complex
> class. This already exposes all the ISO c99 functions. So perhaps it is not
> required to make all the helper functions public for the purpose of
> composing multiple operations. But it would be helpful for all the single
> operations.
>

I may be one or more steps behind, sorry, but I still cannot figure
out how the API is supposed to be applied (IOW, the "use cases").
I'm still at "provide functions that operate on a list of complex numbers".
But the subsequent question: For what purpose?
Some weeks ago (IIRC), I asked the same and whether the only use
case was FFT...

Regards,
Gilles

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-26 Thread Alex Herbert
On Sun, 26 Jun 2022 at 20:52, Sumanth Rajkumar 
wrote:

> Hi,
> I have raised PR #113 after rebasing to the master branch with Alex's
> checkstyle changes
>
> As per feedback, I have made the following changes
> a) Added javadoc comments
> b) Ensured test coverage
> c) Renamed accessors on the interface
>

Thanks for the changes. Note that a new PR is not required. You can simply
force push changes to the previous PR. It is covering the same subject.

I've not yet fully read the PR. However the level of abstraction on some of
the simple functions seems excessive. Many of the scalar operations
using applyScalarFunction are one liners that have been abstracted to
multiple layers of function references. Simple operations such as add,
subtract, conjugate, negate, arg (defined as Math.atan2) may be better left
alone. They can be duplicated into the complex functions class if the API
is for public consumption but performance may be impacted by the
abstraction. The code is definitely made less readable.

Also note that you have some double empty lines which should be a
single empty line and then some functions ending with } and no empty line
after. These can be simply fixed using a regular expression to search for
them.

I note that some javadoc is missing for private methods. I have not set
checkstyle to enforce this and the default scope is public. It should at
least be protected, but my preference would be package. I will see if the
rest of the project is OK for this and then update the rule.


>
>
> > Gilles Sadowski  wrote:
> > In "DComplex", I propose that the accessors be named "real()" and
> > "imag()" (or just
> > "re()" and "im()").  ["DComplex" is not a very satisfying name either...]
>
> For the interface name, shall I change it to Complex64 from DComplex?
>

In c the 'complex' keyword is a suffix:

double complex c1;
float complex c2;
long double complex c3;

In c++ the type is generic (and read as a suffix):

complex c1;
complex c2;

Either of these would be my preference over DComplex or Complex64.


> > Are we sure that all this code needs to be part of the public API?
> > If not, I'd suggest limiting accessibility to "package-private".
>
> Are you referring to the static methods in ComplexFunctions and
> ComplexBiFunctions classes?
> I think they would need to be public for developers to be able to compose
> multiple operations...
>

The static helper functions have been extracted to support all the ISO c99
operations on the list structure of complex numbers.

A list will ideally implement a generic foreach operation. So to apply a
single function only requires making the static functions public. The
alternative is to make the list expose all the ISO c99 operations in its
public API.

To create a composite function that eventually writes back to the list can
be implemented by writing intermediate values to a result which is then
passed to the next operation. This can be satisfied by using the Complex
class. This already exposes all the ISO c99 functions. So perhaps it is not
required to make all the helper functions public for the purpose of
composing multiple operations. But it would be helpful for all the single
operations.


>
> Thanks,
> Sumanth
>
> PS: Noticed master branch unit test failures in numbers-fraction module
>

This has been fixed. Sorry for the mistake.

Alex


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-26 Thread Sumanth Rajkumar
Hi,
I have raised PR #113 after rebasing to the master branch with Alex's
checkstyle changes

As per feedback, I have made the following changes
a) Added javadoc comments
b) Ensured test coverage
c) Renamed accessors on the interface


> Gilles Sadowski  wrote:
> In "DComplex", I propose that the accessors be named "real()" and
> "imag()" (or just
> "re()" and "im()").  ["DComplex" is not a very satisfying name either...]

For the interface name, shall I change it to Complex64 from DComplex?

> Are we sure that all this code needs to be part of the public API?
> If not, I'd suggest limiting accessibility to "package-private".

Are you referring to the static methods in ComplexFunctions and
ComplexBiFunctions classes?
I think they would need to be public for developers to be able to compose
multiple operations...

Thanks,
Sumanth

PS: Noticed master branch unit test failures in numbers-fraction module

On Fri, 24 Jun 2022 at 19:43, Gilles Sadowski  wrote:

> Hello.
>
> Le ven. 24 juin 2022 à 16:59, Sumanth Rajkumar
>  a écrit :
> >
> > Hi Alex, Gilles, and Matt,
> >
> > I have raised a PR to the complex-gsoc-22 branch and it has been linked
> to
> > the NUMBERS-188 jira.
>
> One tenet of a project such as "Commons" is that everything must be
> documented.[1]
> For the Javadoc comments, please apply the same style as in other source
> files.
>
> Formatting should also be taken care of (to help review, and future
> maintenance).[2]
>
> Are we sure that all this code needs to be part of the public API?  If
> not, I'd suggest
> limiting accessibility to "package-private".
>
> In "DComplex", I propose that the accessors be named "real()" and
> "imag()" (or just
> "re()" and "im()").  ["DComplex" is not a very satisfying name either...]
>
> Thanks,
> Gilles
>
> [1] I'm a bit surprised that the build succeeds despite the missing
> comments.
> [2] E.g. one argument per line improves readability (IMHO).
>
> >
> > [...]
>
> -
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-25 Thread Alex Herbert
On Sat, 25 Jun 2022 at 10:07, Alex Herbert  wrote:

>
>
> Checkstyle:
> Checkstyle plugin is configured to failOnViolation. So it is not
> complaining about lack of comments. We are using the following rules:
>
> InvalidJavadocPosition,JavadocMethod,JavadocType,JavadocVariable,JavadocStyle
>
> So the failure of checkstyle to fail is strange. If I take an existing
> file and make some formatting changes it fails the build. If I delete a tag
> from the javadoc it fails the build. If I delete the entire javadoc then
> this passes. So checkstyle checks the existing javadoc but does not fail
> when javadoc is missing. This requires further investigation.
>

This requires extra checks:

MissingJavadocMethod
MissingJavadocPackage
MissingJavadocType

I will add these to our checkstyle configs and fix any failures (since
these are scoped to private by default there may be some missing javadoc).

See:
http://checkstyle.sourceforge.net/config_javadoc.html


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-25 Thread Alex Herbert
On Sat, 25 Jun 2022 at 00:43, Gilles Sadowski  wrote:

>
> [1] I'm a bit surprised that the build succeeds despite the missing
> comments.
>

So am I. There are a lot of warnings:

Compilation has 2 warnings each about unchecked casts and unchecked method
invocation.

PMD: 115 warnings.
This plugin is not set to fail on violation due to problems throughout the
numbers build. But it does spot all the missing javadoc comments.

Javadoc:
2 warnings for incorrect tags. This plugin could be configured to fail on
warning. The default is failOnError=true and failOnWarning=false. I checked
the rest of the project and there are no warnings. So I changed this to
failOnWarning.

Jacoco:
Rule violations for classes covered and methods covered. But it does not
fail the build. I checked the old travis profile and it did not set
the build to fail when coverage is not met. The travis profile just
submitted the report to coveralls.
There is a note in the pom:


false

I have set this to true since we have met coverage goals across the rest of
the numbers project.

Note: The coverage report from codecov is not yet complete so has not been
posted to the PR. It does show the drop in coverage:
https://codecov.io/github/apache/commons-numbers/commit/203cbc6a505a1d004297115414b2188e21427219

Checkstyle:
Checkstyle plugin is configured to failOnViolation. So it is not
complaining about lack of comments. We are using the following rules:
InvalidJavadocPosition,JavadocMethod,JavadocType,JavadocVariable,JavadocStyle

So the failure of checkstyle to fail is strange. If I take an existing file
and make some formatting changes it fails the build. If I delete a tag from
the javadoc it fails the build. If I delete the entire javadoc then this
passes. So checkstyle checks the existing javadoc but does not fail when
javadoc is missing. This requires further investigation.


You will have to rebase the PR on master to pick up the pom changes. Then
run the default maven goal (in the complex module) and fix the issues.

Alex


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-24 Thread Gilles Sadowski
Hello.

Le ven. 24 juin 2022 à 16:59, Sumanth Rajkumar
 a écrit :
>
> Hi Alex, Gilles, and Matt,
>
> I have raised a PR to the complex-gsoc-22 branch and it has been linked to
> the NUMBERS-188 jira.

One tenet of a project such as "Commons" is that everything must be
documented.[1]
For the Javadoc comments, please apply the same style as in other source files.

Formatting should also be taken care of (to help review, and future
maintenance).[2]

Are we sure that all this code needs to be part of the public API?  If
not, I'd suggest
limiting accessibility to "package-private".

In "DComplex", I propose that the accessors be named "real()" and
"imag()" (or just
"re()" and "im()").  ["DComplex" is not a very satisfying name either...]

Thanks,
Gilles

[1] I'm a bit surprised that the build succeeds despite the missing comments.
[2] E.g. one argument per line improves readability (IMHO).

>
> [...]

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-24 Thread Alex Herbert
OK. I have approved the CI build to run on the PR.

I will review when I have some more time.

Alex


On Fri, 24 Jun 2022 at 15:59, Sumanth Rajkumar 
wrote:

> Hi Alex, Gilles, and Matt,
>
> I have raised a PR to the complex-gsoc-22 branch and it has been linked to
> the NUMBERS-188 jira.
>
> While the PR is being reviewed, I will start working on NUMBERS-186 (adding
> support for list and matrix of Complex numbers).
>
> Thanks,
> Sumanth
>
> On Mon, 20 Jun 2022 at 09:43, Sumanth Rajkumar  >
> wrote:
>
> > Hello Gilles,
> > Thanks!  I will start a new thread for float support.
> >
> > Thanks
> > Sumanth
> >
> >
> > On Mon, Jun 20, 2022, 18:41 Gilles Sadowski  wrote
> >
> >>
> >> > Also, should we add support for float data type for complex numbers?
> >>
> >> In the "dev" ML, we customarily aim at focussing each discussion,
> >
> >
> >> Thus could you please start a new thread with this question?
> >>
> >
> >
> >
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-24 Thread Sumanth Rajkumar
Hi Alex, Gilles, and Matt,

I have raised a PR to the complex-gsoc-22 branch and it has been linked to
the NUMBERS-188 jira.

While the PR is being reviewed, I will start working on NUMBERS-186 (adding
support for list and matrix of Complex numbers).

Thanks,
Sumanth

On Mon, 20 Jun 2022 at 09:43, Sumanth Rajkumar 
wrote:

> Hello Gilles,
> Thanks!  I will start a new thread for float support.
>
> Thanks
> Sumanth
>
>
> On Mon, Jun 20, 2022, 18:41 Gilles Sadowski  wrote
>
>>
>> > Also, should we add support for float data type for complex numbers?
>>
>> In the "dev" ML, we customarily aim at focussing each discussion,
>
>
>> Thus could you please start a new thread with this question?
>>
>
>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-20 Thread Sumanth Rajkumar
Hello Gilles,
Thanks!  I will start a new thread for float support.

Thanks
Sumanth


On Mon, Jun 20, 2022, 18:41 Gilles Sadowski  wrote

>
> > Also, should we add support for float data type for complex numbers?
>
> In the "dev" ML, we customarily aim at focussing each discussion,


> Thus could you please start a new thread with this question?
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-20 Thread Gilles Sadowski
Hello Sumanth.

Le lun. 20 juin 2022 à 07:05, Sumanth Rajkumar
 a écrit :
>
> [...]
>
> Also, should we add support for float data type for complex numbers?

In the "dev" ML, we customarily aim at focussing each discussion, so
that people can easily decide (ideally, from the "Subject:" line) if they
want to voice some opinion.  [This also improves searches in the ML
archive.]
Thus could you please start a new thread with this question?
[Note that the relationships between all technical issues related to the
extension of the functionalities around "Complex" is better managed
through links between JIRA issues than by lengthy threads here.]

Thanks,
Gilles

>
> [...]

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-19 Thread Sumanth Rajkumar
Hi Alex, Matt, and Gilles,

As discussed on the other thread, I have made NUMBERS-186 (for complex
lists work) the child of a parent ticket (NUMBERS-187)

I have created NUMBERS-188 for the functional interfaces and static method
refactoring of the existing instance methods of Complex class.

I hurt my shoulders over the weekend and have been advised few days rest. I
expect to have the PR for NUMBERS-188 ready for review by Thursday.

Also, should we add support for float data type for complex numbers?

If yes, should we reuse static functions that operate on double types and
use Java float-double widening and narrowing conversions?

https://docs.oracle.com/javase/specs/jls/se10/html/jls-5.html#jls-5.1.2

If no, should we have separate static complex functions for float types?

I can raise a ticket for supporting float types based on feedback.

Thanks,
Sumanth


On Thu, 16 Jun 2022 at 08:11, Sumanth Rajkumar 
wrote:

> > EjML functional interface looks like this
> >
> >  void apply(ComplexDouble in, MutableComplexDouble out)
> >
> Similar to the mutable cursor idea we have been discussing. The Mutable
> object could be an interface?
>
> Ok
>
> We may need to have more than one implementation of the underlying storage.
> Using interleaved real and imaginary will be more efficient for computation
> on a single number due to cache reads from memory. But the separate arrays
> are going to be useful when writing code with the vector API that requires
> extracting blocks of real or imaginary components.
>
>  Ok
>
>
> >
> >
> > I am still wondering how these functions can be composed. Here are a few
> > ideas
> >
> > This may need more work..
>
>
> > ComplexResultInterceptor class
>
> It does require a lot of code that may have a far bigger overhead impact
> than just creating a complex result.
>
>
>
>
> I think the overhead of creating the Complex objects for the intermediates
> may be lower than a solution that tries to avoid allocation overhead with
> complexity of ThreadLocal. A performance benchmark would be able to
> determine this so we can look at that in the future.
>
>
>  Ok. Will extend java functions and create complex objects for
> intermediate results
>
>
> It may be useful here to create a branch in the numbers repository for all
> the changes. To keep it simple perhaps a 'develop' branch can be used that
> you can make your changes against.
>
>
> Ok.
> I can raise a PR to develop with the above changes. I will follow Alex's
> latest update to the Developer Guide for pull requests.
>
>
> Thanks,
>
> Sumanth
>
>
> On Wed, 15 Jun 2022 at 13:58, Alex Herbert 
> wrote:
>
>> On Wed, 15 Jun 2022 at 17:38, Sumanth Rajkumar <
>> rajkumar.suma...@gmail.com>
>> wrote:
>>
>> > Hi Alex,
>> >
>> > What do you intend to support as a "Matrix"? Is it for 2D or ND? What
>> > functionality already exists for complex matrix operations such as add
>> and
>> > multiply in for example EJML?
>> >
>> > This may require some expansion.
>> >
>> > a) I reviewed EJML data naming conventions, this is what they follow:
>> >
>> >
>> >
>> https://github.com/lessthanoptimal/ejml#procedural-api-matrix-and-class-names
>> > Should we follow this approach as well?
>> >I wasn't thinking about implementing ND right now, maybe I can during
>> > Phase 2?
>> >
>>
>> OK.
>>
>>
>> >
>> > b) EJML only supports 2D matrices with vector (1XN) being a special
>> case,
>> > should I do that too?
>> >
>>
>> OK.
>>
>>
>> >
>> > c) EJML uses a mutable ComplexResult, they use a single mutable class
>> for
>> > both input and output and return void
>> >
>> > Here is the link to their implementation:
>> >
>> >
>> >
>> https://github.com/lessthanoptimal/ejml/blob/SNAPSHOT/main/ejml-core/src/org/ejml/ops/ComplexMath_F64.java
>> >
>> > Their functional interface looks like this
>> >
>> >  void apply(ComplexDouble in, MutableComplexDouble out)
>> >
>>
>> Similar to the mutable cursor idea we have been discussing. The Mutable
>> object could be an interface?
>>
>>
>> >
>> > d) For dense Matrix internal storage, I'm planning on using separate
>> arrays
>> > (or a single array where the first half of the array will be real and
>> the
>> > second half will be imaginary) instead of alternating real and imaginary
>> > because it allows us to optimize space for pure imaginary or real
>> matrices.
>> >
>> > Is that ok?
>> >
>>
>> We may need to have more than one implementation of the underlying
>> storage.
>> Using interleaved real and imaginary will be more efficient for
>> computation
>> on a single number due to cache reads from memory. But the separate arrays
>> are going to be useful when writing code with the vector API that requires
>> extracting blocks of real or imaginary components.
>>
>>
>> >
>> >
>> > I am still wondering how these functions can be composed. Here are a few
>> > ideas
>> >
>> >
>> > This may need more work..
>> >
>> >
>> > I have provided an approach below using an intermediate
>> > ComplexResultInterceptor 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-16 Thread Sumanth Rajkumar
> EjML functional interface looks like this
>
>  void apply(ComplexDouble in, MutableComplexDouble out)
>
Similar to the mutable cursor idea we have been discussing. The Mutable
object could be an interface?

Ok

We may need to have more than one implementation of the underlying storage.
Using interleaved real and imaginary will be more efficient for computation
on a single number due to cache reads from memory. But the separate arrays
are going to be useful when writing code with the vector API that requires
extracting blocks of real or imaginary components.

 Ok


>
>
> I am still wondering how these functions can be composed. Here are a few
> ideas
>
> This may need more work..


> ComplexResultInterceptor class

It does require a lot of code that may have a far bigger overhead impact
than just creating a complex result.




I think the overhead of creating the Complex objects for the intermediates
may be lower than a solution that tries to avoid allocation overhead with
complexity of ThreadLocal. A performance benchmark would be able to
determine this so we can look at that in the future.


 Ok. Will extend java functions and create complex objects for intermediate
results


It may be useful here to create a branch in the numbers repository for all
the changes. To keep it simple perhaps a 'develop' branch can be used that
you can make your changes against.


Ok.
I can raise a PR to develop with the above changes. I will follow Alex's
latest update to the Developer Guide for pull requests.


Thanks,

Sumanth


On Wed, 15 Jun 2022 at 13:58, Alex Herbert  wrote:

> On Wed, 15 Jun 2022 at 17:38, Sumanth Rajkumar  >
> wrote:
>
> > Hi Alex,
> >
> > What do you intend to support as a "Matrix"? Is it for 2D or ND? What
> > functionality already exists for complex matrix operations such as add
> and
> > multiply in for example EJML?
> >
> > This may require some expansion.
> >
> > a) I reviewed EJML data naming conventions, this is what they follow:
> >
> >
> >
> https://github.com/lessthanoptimal/ejml#procedural-api-matrix-and-class-names
> > Should we follow this approach as well?
> >I wasn't thinking about implementing ND right now, maybe I can during
> > Phase 2?
> >
>
> OK.
>
>
> >
> > b) EJML only supports 2D matrices with vector (1XN) being a special case,
> > should I do that too?
> >
>
> OK.
>
>
> >
> > c) EJML uses a mutable ComplexResult, they use a single mutable class for
> > both input and output and return void
> >
> > Here is the link to their implementation:
> >
> >
> >
> https://github.com/lessthanoptimal/ejml/blob/SNAPSHOT/main/ejml-core/src/org/ejml/ops/ComplexMath_F64.java
> >
> > Their functional interface looks like this
> >
> >  void apply(ComplexDouble in, MutableComplexDouble out)
> >
>
> Similar to the mutable cursor idea we have been discussing. The Mutable
> object could be an interface?
>
>
> >
> > d) For dense Matrix internal storage, I'm planning on using separate
> arrays
> > (or a single array where the first half of the array will be real and the
> > second half will be imaginary) instead of alternating real and imaginary
> > because it allows us to optimize space for pure imaginary or real
> matrices.
> >
> > Is that ok?
> >
>
> We may need to have more than one implementation of the underlying storage.
> Using interleaved real and imaginary will be more efficient for computation
> on a single number due to cache reads from memory. But the separate arrays
> are going to be useful when writing code with the vector API that requires
> extracting blocks of real or imaginary components.
>
>
> >
> >
> > I am still wondering how these functions can be composed. Here are a few
> > ideas
> >
> >
> > This may need more work..
> >
> >
> > I have provided an approach below using an intermediate
> > ComplexResultInterceptor class that is thread-safe and minimizes object
> > creation using thread local and stacks. It also doesn't require
> > ComplexDouble constraint for the generic R result type.
> >
>
> It does require a lot of code that may have a far bigger overhead impact
> than just creating a complex result.
>
> Since thread safety requires an intermediate be stored then it may make
> more sense to expand the API to allow operations on a list using a unary
> operator of complex:
>
> UnaryOperator op;
>
> You can then create your function to work on a complex number and chain
> them together using the standard java 8 functions. This could be supported
> for the ISO c99 functions by just using Complex. Unfortunately this does
> not work as the UnaryOperator has not overridden andThen and compose for
> the single argument. This is valid:
>
> UnaryOperator op = Complex::sqrt;
> // These compose to Function
> Function op2 = op.andThen(Complex::conj);
> Function op3 = op.compose(Complex::conj);
>
> // Invalid to assign back to UnaryOperator
> op = op.andThen(Complex::conj);
> // OK with a cast
> op = (UnaryOperator) op.andThen(Complex::conj);
>
> // In use:
> 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-15 Thread Alex Herbert
On Wed, 15 Jun 2022 at 17:38, Sumanth Rajkumar 
wrote:

> Hi Alex,
>
> What do you intend to support as a "Matrix"? Is it for 2D or ND? What
> functionality already exists for complex matrix operations such as add and
> multiply in for example EJML?
>
> This may require some expansion.
>
> a) I reviewed EJML data naming conventions, this is what they follow:
>
>
> https://github.com/lessthanoptimal/ejml#procedural-api-matrix-and-class-names
> Should we follow this approach as well?
>I wasn't thinking about implementing ND right now, maybe I can during
> Phase 2?
>

OK.


>
> b) EJML only supports 2D matrices with vector (1XN) being a special case,
> should I do that too?
>

OK.


>
> c) EJML uses a mutable ComplexResult, they use a single mutable class for
> both input and output and return void
>
> Here is the link to their implementation:
>
>
> https://github.com/lessthanoptimal/ejml/blob/SNAPSHOT/main/ejml-core/src/org/ejml/ops/ComplexMath_F64.java
>
> Their functional interface looks like this
>
>  void apply(ComplexDouble in, MutableComplexDouble out)
>

Similar to the mutable cursor idea we have been discussing. The Mutable
object could be an interface?


>
> d) For dense Matrix internal storage, I'm planning on using separate arrays
> (or a single array where the first half of the array will be real and the
> second half will be imaginary) instead of alternating real and imaginary
> because it allows us to optimize space for pure imaginary or real matrices.
>
> Is that ok?
>

We may need to have more than one implementation of the underlying storage.
Using interleaved real and imaginary will be more efficient for computation
on a single number due to cache reads from memory. But the separate arrays
are going to be useful when writing code with the vector API that requires
extracting blocks of real or imaginary components.


>
>
> I am still wondering how these functions can be composed. Here are a few
> ideas
>
>
> This may need more work..
>
>
> I have provided an approach below using an intermediate
> ComplexResultInterceptor class that is thread-safe and minimizes object
> creation using thread local and stacks. It also doesn't require
> ComplexDouble constraint for the generic R result type.
>

It does require a lot of code that may have a far bigger overhead impact
than just creating a complex result.

Since thread safety requires an intermediate be stored then it may make
more sense to expand the API to allow operations on a list using a unary
operator of complex:

UnaryOperator op;

You can then create your function to work on a complex number and chain
them together using the standard java 8 functions. This could be supported
for the ISO c99 functions by just using Complex. Unfortunately this does
not work as the UnaryOperator has not overridden andThen and compose for
the single argument. This is valid:

UnaryOperator op = Complex::sqrt;
// These compose to Function
Function op2 = op.andThen(Complex::conj);
Function op3 = op.compose(Complex::conj);

// Invalid to assign back to UnaryOperator
op = op.andThen(Complex::conj);
// OK with a cast
op = (UnaryOperator) op.andThen(Complex::conj);

// In use:
// op could be declared as a UnaryOperator or Function to just use the JDK functions as is with full support for chaining.
list.forEach(op);

To avoid the cast you can extend Function to add e.g.

default UnaryOperator andThen(UnaryOperator after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}

I do not know why the JDK has not done this. It seems to compile on my
machine but I've not tested it.

I think the overhead of creating the Complex objects for the intermediates
may be lower than a solution that tries to avoid allocation overhead with
complexity of ThreadLocal. A performance benchmark would be able to
determine this so we can look at that in the future.


> I'm working on this right now, I've refactored most of the existing
> instance methods and I should be done by tomorrow
>

OK.

It may be useful here to create a branch in the numbers repository for all
the changes. To keep it simple perhaps a 'develop' branch can be used that
you can make your changes against.

Alex


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-15 Thread Sumanth Rajkumar
Hi Alex,

What do you intend to support as a "Matrix"? Is it for 2D or ND? What
functionality already exists for complex matrix operations such as add and
multiply in for example EJML?

This may require some expansion.

a) I reviewed EJML data naming conventions, this is what they follow:

https://github.com/lessthanoptimal/ejml#procedural-api-matrix-and-class-names
Should we follow this approach as well?
   I wasn't thinking about implementing ND right now, maybe I can during
Phase 2?

b) EJML only supports 2D matrices with vector (1XN) being a special case,
should I do that too?

c) EJML uses a mutable ComplexResult, they use a single mutable class for
both input and output and return void

Here is the link to their implementation:

https://github.com/lessthanoptimal/ejml/blob/SNAPSHOT/main/ejml-core/src/org/ejml/ops/ComplexMath_F64.java

Their functional interface looks like this

 void apply(ComplexDouble in, MutableComplexDouble out)

d) For dense Matrix internal storage, I'm planning on using separate arrays
(or a single array where the first half of the array will be real and the
second half will be imaginary) instead of alternating real and imaginary
because it allows us to optimize space for pure imaginary or real matrices.

Is that ok?


I am still wondering how these functions can be composed. Here are a few
ideas


This may need more work..


I have provided an approach below using an intermediate
ComplexResultInterceptor class that is thread-safe and minimizes object
creation using thread local and stacks. It also doesn't require
ComplexDouble constraint for the generic R result type.

@FunctionalInterface
public interface ComplexFunction {

default R apply(Complex c, ComplexResult result) {
return apply(c.real(), c.imag(), result);
}
R apply(double r, double i, ComplexResult result);

default  ComplexFunction thenApply(ComplexFunction
afterFunction) {
return (x, y, afterResult) -> {
ComplexResultInterceptor interceptor =
ComplexResultInterceptor.TLOCAL_ResultInterceptor.get();
interceptor.pushResultProvider(afterFunction, afterResult);
apply(x, y, interceptor);
return interceptor.popResult();
};
}
}

public class ComplexResultInterceptor implements ComplexResult {

private Stack> afterResultProviderStack = new
Stack<>();
private Stack> afterFunctionStack= new Stack<>();
private Stack afterResult = new Stack<>();

public static final ThreadLocal
TLOCAL_ResultInterceptor = ThreadLocal.withInitial(() -> new
ComplexResultInterceptor());

private static final AtomicLong counter = new AtomicLong();

private ComplexResultInterceptor() {
System.out.println("Allocating ComplexResultInterceptor # " +
counter.incrementAndGet());
}

public  void pushResultProvider(ComplexFunction func,
ComplexResult provider) {
afterFunctionStack.push(func);
afterResultProviderStack.push(provider);
}

@Override
public R apply(double r, double i) {
ComplexFunction after = afterFunctionStack.pop();
ComplexResult resultProvider = afterResultProviderStack.pop();
afterResult.push(after.apply(r, i, resultProvider));
return null;
}

public  U popResult() {
return (U) afterResult.pop();
}
}

Here is a link to the unit test class that ran successfully and the
ComplexResultInterceptor class:
https://github.com/sumanth-rajkumar/commons-numbers/blob/sumanth-gsoc-22-array_refactor/commons-numbers-complex/src/test/java/org/apache/commons/numbers/complex/ComplexComposeTest.java
https://github.com/sumanth-rajkumar/commons-numbers/blob/sumanth-gsoc-22-array_refactor/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexResultInterceptor.java


> 4) Refactor existing instance methods in Complex class as static functions
> in ComplexDoubleFunctions class using functional interface signatures
>


I would start with this. It can always be updated if the functional
interface is later modified.


I'm working on this right now, I've refactored most of the existing
instance methods and I should be done by tomorrow

Thanks,

Sumanth


On Mon, 13 Jun 2022 at 06:26, Alex Herbert  wrote:

> On Mon, 13 Jun 2022 at 07:47, Sumanth Rajkumar  >
> wrote:
>
> >
> >
> > For Phase 1, I propose to do the following
> >
> >
> > 1) Introduce ComplexDouble, ComplexDoubleVector and ComplexDoubleMatrix
> > interfaces
> >
>
> What do you intend to support as a "Matrix"? Is it for 2D or ND? What
> functionality already exists for complex matrix operations such as add and
> multiply in for example EJML?
>
> This may require some expansion.
>
>
> > The interfaces to have methods for applying below unary and binary
> > double functions
> > The interfaces to have methods to convert to/from primitive double
> > arrays (both separate arrays for real/imaginary and single interleaved
> > array)
> > The interfaces to 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-13 Thread Alex Herbert
On Mon, 13 Jun 2022 at 07:47, Sumanth Rajkumar 
wrote:

>
>
> For Phase 1, I propose to do the following
>
>
> 1) Introduce ComplexDouble, ComplexDoubleVector and ComplexDoubleMatrix
> interfaces
>

What do you intend to support as a "Matrix"? Is it for 2D or ND? What
functionality already exists for complex matrix operations such as add and
multiply in for example EJML?

This may require some expansion.


> The interfaces to have methods for applying below unary and binary
> double functions
> The interfaces to have methods to convert to/from primitive double
> arrays (both separate arrays for real/imaginary and single interleaved
> array)
> The interfaces to have methods to convert to/from DoubleBuffer (both
> separate arrays for real/imaginary and single interleaved buffer)
>
> 2) Introduce generic (item based) functional interfaces for unary and
> binary double functions
>
> @FunctionalInterface
> public interface ComplexDoubleFunction {
>
> R apply(double real, double imaginary, ComplexDoubleResult result);
> }
>
> @FunctionalInterface
> public interface ComplexDoubleBiFunction {
>
> R apply(double real1, double imaginary1, double real2, double imaginary2,
>  ComplexDoubleResult result);
> }
>
> @FunctionalInterface
> public interface ComplexDoubleResult {
>
> R apply(double r, double i);
>
> }
>
>
I am still wondering how these functions can be composed. Here are a few
ideas based on requiring that the functional interface generic type is a
ComplexDouble. This allows the result single item R to be decomposed again
into real and imaginary parts to pass to the next method.

public static  R conj(double r, double i, ComplexResult result) {
return result.apply(r, -i);
}

public static  R multiplyImaginary(double r, double i, ComplexResult
result) {
return result.apply(-i, r);
}

@FunctionalInterface
public interface ComplexDoubleFunction {

default R apply(ComplexDouble c, ComplexResult result) {
return apply(c.real(), c.imag(), result);
}

R apply(double r, double i, ComplexResult result);

default  ComplexDoubleFunction
andThen(ComplexDoubleFunction after,
ComplexResult intermediateResult) {
Objects.requireNonNull(after);
// Requires the intermediate which would be the terminal result if
the function is not composed.
return (r, i, result) -> after.apply(apply(r, i,
intermediateResult), result);
}

default  ComplexDoubleFunction
andThen2(ComplexDoubleFunction after) {
Objects.requireNonNull(after);
return (re, im, result) -> {
// Fabricate the intermediate. Function is not thread safe.
double[] parts = {0, 0};
ComplexResult intermediateResult = (x, y) -> {
parts[0] = x;
parts[1] = y;
return null;
};
R t = apply(re, im, intermediateResult);
return after.apply(t, result);
};
}

default ComplexDoubleFunction andThen(ComplexDoubleFunction
after) {
Objects.requireNonNull(after);
// Thread safe. The intermediate is also the terminal result. This
is not optimal if the intermediate/terminal is a list with inefficient
read/write to the current position.
return (r, i, result) -> after.apply(apply(r, i, result), result);
}
}

public static void example() {
ComplexDoubleFunction fun = ComplexDoubleFunctions::conj;
ComplexDoubleFunction fun2 =
ComplexDoubleFunctions::multiplyImaginary;
ComplexDoubleFunction fun3 =
ComplexDoubleFunctions::multiplyImaginary;
// Not allowed as Void does not extend ComplexDouble
//ComplexDoubleFunction fun4 =
ComplexDoubleFunctions::multiplyImaginary;

ComplexDoubleFunction funA = fun.andThen(fun2);
// Not allowed
//ComplexDoubleFunction funA2 = fun.andThen(fun2);
ComplexDoubleFunction funB = fun.andThen2(fun3);
ComplexDoubleFunction funC = fun.andThen(fun3,
Complex::ofCartesian);
}

However you cannot create a ComplexDoubleFunction which will not
return a result as the interface is typed to ComplexDouble. Not returning a
final result is the usage required by list operations that do not return
results but write back to storage in ComplexResult.

Composite function requires an intermediate to hold the result to pass to
the next function. If this is the same object then the function will not be
thread-safe.

This may need more work...


> 4) Refactor existing instance methods in Complex class as static functions
> in ComplexDoubleFunctions class using functional interface signatures
>

I would start with this. It can always be updated if the functional
interface is later modified.

Alex


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-13 Thread Sumanth Rajkumar
Thanks Alex for the detailed feedback.

As GSOC Phase 1 has started, for the existing C99 complex functions in
Complex class, I will refactor using the item based functional interface
approach.

I can look at a Range based approach later if I have time.
As you mentioned the C99 functions cannot take advantage of the limited
Java 16 Vector API features.
However, it may be possible to speed up C99 functions using GPUs based on
quick look at documentation here

https://aparapi.com/introduction/getting-started.html
https://aparapi.com/documentation/kernel-guidelines.html
https://aparapi.com/documentation/aparapi-patterns.html
https://git.qoto.org/aparapi/aparapi-examples/-/blob/master/examples/movie/src/com/amd/aparapi/examples/movie/AparapiSolution.java


For Phase 1, I propose to do the following


1) Introduce ComplexDouble, ComplexDoubleVector and ComplexDoubleMatrix
interfaces
The interfaces to have methods for applying below unary and binary
double functions
The interfaces to have methods to convert to/from primitive double
arrays (both separate arrays for real/imaginary and single interleaved
array)
The interfaces to have methods to convert to/from DoubleBuffer (both
separate arrays for real/imaginary and single interleaved buffer)

2) Introduce generic (item based) functional interfaces for unary and
binary double functions

@FunctionalInterface
public interface ComplexDoubleFunction {

R apply(double real, double imaginary, ComplexDoubleResult result);
}

@FunctionalInterface
public interface ComplexDoubleBiFunction {

R apply(double real1, double imaginary1, double real2, double imaginary2,
 ComplexDoubleResult result);
}

@FunctionalInterface
public interface ComplexDoubleResult {

R apply(double r, double i);

}



3) Add ComplexDouble interface to Complex class.
   Add ComplexDoubleVectorImpl (primitive double array backing)
implementation for ComplexDoubleVector interface
   Add ComplexDoubleMatrixImpl (primitive double array backing)
implementation for ComplexDoubleMatrix interface

4) Refactor existing instance methods in Complex class as static functions
in ComplexDoubleFunctions class using functional interface signatures


5) Add concurrency support for operations on Vector and Matrix objects


interface ComplexDoubleVector {

  default ComplexDoubleVector apply(ComplexDoubleFunction
function) {
return apply(function, 0, size(), 1);
 }

 default ComplexDoubleVector apply(ComplexDoubleFunction
function, int concurrency) {
 return apply(function, 0, size(), 1);
 }

ComplexDoubleVector apply(ComplexDoubleFunction function, int
start, int length, int concurrency)
}

ComplexDoubleMatrixImpl and ComplexDoubleVectorImpl implement concurrency
(if concurrency > 1) by partitioning the data and execute using fork join
thread pool (No use of streams)


6) Unit tests for Vector and Matrix implementations

Let me know if you need anything else or reduce the scope for phase 1

Thanks
Sumanth

On Sun, 12 Jun 2022 at 20:08, Alex Herbert  wrote:

> On Sun, 12 Jun 2022 at 16:55, Sumanth Rajkumar  >
> wrote:
>
> >
> >
> > I have provided both approaches. Functional interfaces that operate on
> > single complex and on Arrays
> >
>
> Thanks for the examples.
>
>
> > <-- SNIP -->
> >
> >   Here the implementation including iteration/cursors has moved to the
> > array based Lambda.
> >   For Complex arrays, I think it is beneficial to move the iteration
> logic
> > from data storage (ComplexList) to the Lambda  (ComplexFunctions::conj)
> >
>
> Possible mix up between lambda and method reference? I certainly would not
> want to write a lambda function (anonymous method) that is responsible for
> iteration; I would stick to providing a simple unary operator that can be
> passed to a list to act on each member.
>
> Re: Iteration logic in the array method. I am not sure about this. If the
> underlying data is not linear (e.g. a 2D double[][]) then performing a
> range based method on it may not be optimal. It should be up to the
> implementation to decide the optimal iteration over the underlying data,
> possibly specialising a spliterator to split based on stripes of the
> underlying data.
>
> Anyway, this set of examples for item-based or range-based approaches
> confers no benefit to the range based approach. It just does a potentially
> sub-optimal iteration of a unary operator on each item. But this is due to
> the example not being a true range based operation. I think the range based
> API should be based around operations that require access to more than one
> element in the range in order to function. For example this would be
> transform operations.
>
> All the other examples we have act on single complex numbers. In this case
> an operator is provided to act on the complex and create a complex result.
> This can be passed to the container which will optimally iterate over the
> data, or sub-range of, and apply the operation.
>
> One issue is parallelisation using a stream. By 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-12 Thread Alex Herbert
On Sun, 12 Jun 2022 at 16:55, Sumanth Rajkumar 
wrote:

>
>
> I have provided both approaches. Functional interfaces that operate on
> single complex and on Arrays
>

Thanks for the examples.


> <-- SNIP -->
>
>   Here the implementation including iteration/cursors has moved to the
> array based Lambda.
>   For Complex arrays, I think it is beneficial to move the iteration logic
> from data storage (ComplexList) to the Lambda  (ComplexFunctions::conj)
>

Possible mix up between lambda and method reference? I certainly would not
want to write a lambda function (anonymous method) that is responsible for
iteration; I would stick to providing a simple unary operator that can be
passed to a list to act on each member.

Re: Iteration logic in the array method. I am not sure about this. If the
underlying data is not linear (e.g. a 2D double[][]) then performing a
range based method on it may not be optimal. It should be up to the
implementation to decide the optimal iteration over the underlying data,
possibly specialising a spliterator to split based on stripes of the
underlying data.

Anyway, this set of examples for item-based or range-based approaches
confers no benefit to the range based approach. It just does a potentially
sub-optimal iteration of a unary operator on each item. But this is due to
the example not being a true range based operation. I think the range based
API should be based around operations that require access to more than one
element in the range in order to function. For example this would be
transform operations.

All the other examples we have act on single complex numbers. In this case
an operator is provided to act on the complex and create a complex result.
This can be passed to the container which will optimally iterate over the
data, or sub-range of, and apply the operation.

One issue is parallelisation using a stream. By its nature the stream acts
on single items; the results are then collated at the end. The stream does
not hold indices for each item. So you cannot use a terminal foreach()
method on each sub-range created by splitting and write back to the
original storage. The stream would have to be declared as ordered to
maintain the original order for the output and this can be collated at the
end to new storage.

To use the stream API with a parallel implementation and zero-allocation
for the terminal operation would require the stream contains an item that
allows read and write. So you can use ComplexDoubleArray:

Stream s;
Consumer op;
s.forEach(op);

Here the operator has to have an array that knows its start and length.
This would be more like a buffer. Each terminal forEach would require a
different instance of ComplexDoubleArray that holds its own start and
length. These may be accessed directly or via an iterator that provides
read and write to each element in the range. The ComplexDoubleArray can
wrap the same underlying data so the only allocation is the object in the
stream wrapping the data and a range to act on. This would be N objects
allocated equal to the number of threads.

Then you write a function that accepts a ComplexDoubleArray and writes back
to the same array. I do not see how this is any better than streaming a
mutable complex:

Stream s;
Consumer op;
s.forEach(op);

ComplexNumber simply has read/write for real and imaginary parts and your
operator can do what it requires. Here ComplexNumber is some object
allocated once in the forEach method that acts as a cursor over the
underlying data.

However the stream examples can be misused. The ultimate method can accept
the stream objects and use them for something else. For example the
ComplexDoubleArray covering part of the range can then be added to
(assuming the ComplexDoubleArray is also a List). So the sub-range
should be a correct subList implementation. The ComplexNumber cursor could
be added to a List which would have many entries but
ultimately only N actual numbers (N=parallel threads) if the ComplexNumber
was a recycled cursor object. So the specialised stream methods should not
be public.

Instead you could create your operators using factory methods. Here are
examples for single-thread and parallel implementation. The parallel
implementation uses the stream API to efficiently divide the range.

public class ComplexFunctions {
public static ComplexDoubleUnaryOperator create(ComplexFunction
operator) {
return new ComplexDoubleUnaryOperator() {
@Override
public ComplexDoubleArray apply(ComplexDoubleArray input,
ComplexDoubleArray result) {
for (int i = 0; i < input.size(); i++) {
final int index = i;
ComplexDouble c = input.get(i);
operator.apply(c.real(), c.imag(), (re, im) -> {
result.setValue(index, re, im);
return null;
});
}
return result;
}
};
}


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-12 Thread Sumanth Rajkumar
>
>
> Some thoughts:
>
> - an array should be mutable by default. It would be made immutable using a
> Collections.immutableX(...) type wrapper.
> - an array should have get and set methods for complex, real and imaginary
> using an index within the array size.
>

Ok

The last two requirements bring us back to the requirement for a generic
> way to write the result of a complex number computation (i.e. a single
> [real, imaginary] pair).
>


I have provided both approaches. Functional interfaces that operate on
single complex and on Arrays

Source available here
https://github.com/sumanth-rajkumar/commons-numbers/tree/98fbedeb7ed3e99597f461d88856b4d94c53343d/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex

I have summarized the approaches below

1) Functional interfaces
Single Pair Approach

@FunctionalInterface
public interface ComplexFunction {

R apply(double r, double i, ComplexResult result);
}

@FunctionalInterface
public  interface ComplexResult {

R apply(double r, double i);
}


Array Approach
@FunctionalInterface
public interface ComplexDoubleUnaryOperator {
ComplexDoubleArray apply(ComplexDoubleArray input, ComplexDoubleArray
result);
}

@FunctionalInterface
public  interface ComplexArrayResult {

R set(int index, double r, double i);

}

interface ComplexDoubleArray extends Iterable,
ComplexArrayResult {

...

}



2) Implementation for conjugate example in ComplexFunctions

https://github.com/sumanth-rajkumar/commons-numbers/blob/98fbedeb7ed3e99597f461d88856b4d94c53343d/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexFunctions.java#L779

Single Pair Approach

 public static  R conj(double r, double i, ComplexResult result) {
return result.apply(r, -i);
}


Array Approach (the implementation below can be different in
ComplexParallelFunctions for example)

public static ComplexDoubleArray conj(ComplexDoubleArray input,
ComplexDoubleArray out) {
final int len = input.size();
for (int i = 0; i < len; i++) {
ComplexDouble c = input.get(i);
out = arrayConj(c.real(), c.imag(), out, i);
}
return out;
}

public static ComplexDoubleArray arrayConj(double r, double i,
 ComplexArrayResult
resultConsumer, int index) {
return resultConsumer.set(index, r, -i);
}

3) Usage of conj in Complex class

https://github.com/sumanth-rajkumar/commons-numbers/blob/98fbedeb7ed3e99597f461d88856b4d94c53343d/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java#L1127

Single Pair Approach

Complex implements Serializable, ComplexDouble {

   public Complex conj() {
 return this.applyUnaryOperator(ComplexFunctions::conj);
 }

public Complex applyUnaryOperator(ComplexFunction
operator) {
return operator.apply(this.real, this.imaginary,
Complex::ofCartesian);
}
}


Array Approach

Complex implements Serializable, ComplexDoubleArray, ComplexDouble {

   public Complex conj() {
 return this.apply(ComplexFunctions::conj);
 }
}

4) Usage of conj in ComplexList (implements
ComplexDoubleArray)


Single Pair Approach

ComplexList {

public ComplexList conj() {
return this.forEach(ComplexFunctions::conj);
}

public ComplexList forEach(ComplexFunction operator) {
   . . .
Cursor cursor = new Cursor(..);
for (int i = 0; i < len; i++) {
cursor.setIndex(i);
operator.apply(cursor.getReal(), cursor.getImginary(), cursor);
}
}

private final class Cursor  implements ComplexDouble, ComplexResult {
  . . .
}

}

Array Approach
   ComplexList implements ComplexDoubleArray {

 public ComplexList conj() {
 return this.apply(ComplexFunctions::conj);
  }

   }

  Here the implementation including iteration/cursors has moved to the
array based Lambda.
  For Complex arrays, I think it is beneficial to move the iteration logic
from data storage (ComplexList) to the Lambda  (ComplexFunctions::conj)

 This would allow developers to use different Lambdas for the same
operation/on the same list



What are you streaming? ComplexDoubleArray sub-arrays? Would the
> ComplexParrallelStreamFunctions class be responsible for creating the
> Spliterator for this to control sub-ranges?
>

Yes. The parallelization details would be abstracted by
ComplexParrallelFunctions
ComplexFunctions could provide the sequential cursor implementation as you
had suggested before

The different implementations abstracted by functional interface would only
be possible with Array based approach

The developer could choose explicitly to call
list.apply(ComplexFunctions::conj) or
list.apply(ComplexParallelFunctions::conj)


ComplexList.conj() could choose to apply sequential or parallel etc based
on some config.



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-12 Thread Alex Herbert
On Sun, 12 Jun 2022 at 04:37, Sumanth Rajkumar 
wrote:

> On Sat, Jun 11, 2022, 18:02 Gilles Sadowski  wrote:
>
> > I have a hard time figuring out whether these bits of code are
> > intended to become the application developer API...
> > What data-structure(s) will be visible (from the application)?
> > What will be hidden ("implementation details")?
> >
>
> Developer API will look something like this
>
> //1) Static methods to initialize array from external forms
>
> ComplexDoubleArray a = ComplexDoubleArray.fromBuffer(Double Buffer);
> ComplexDoubleArray b = ComplexDoubleArray.fromArray(double[]);
>
> ComplexDoubleArray c = ComplexDoubleArray.parseFile(File);
>
>
> //2)  Methods on Array interface for complex operations. One for each
> functional interface type.. unary, binary, scalar operations
>
> @FunctionalInterface
> interface ComplexDoubleUnaryOperator {
>
> ComplexDoubleArray apply(ComplexDoubleArray input, ComplexDoubleArray
> result);
> }
>
> interface ComplexDoubleArray {
>
> int size();
>
> //MutableComplexDoubleArray extends ComplexDoubleArray with setter,
> mutation and static methods to allocate capacity
>
> MutableComplexDoubleArray asMutable();
>
> ComplexDoubleArray asImmutable();
>
> default boolean isImmutable() { return true;}
>
>
>   default ComplexDoubleArray apply(ComplexDoubleUnaryOperator op){
>
> return op.apply(this, result);
>
> }
>
> . . .
>
> }
>

Some thoughts:

- an array should be mutable by default. It would be made immutable using a
Collections.immutableX(...) type wrapper.
- an array should have get and set methods for complex, real and imaginary
using an index within the array size.
- a functional interface should be created that allows generic
specification of the operation to perform on each atomic unit (i.e. a
single complex number) as a lambda function.
- two arrays (a and b) should be able to be paired for an operation on all
pairs of (a, b), specified by a functional interface that can be written as
a lambda function. This method will write in-place to a or an optional
output array c. This could be preallocated, supplied dynamically using a
T[]::new lambda function or some other variant.

The last two requirements bring us back to the requirement for a generic
way to write the result of a complex number computation (i.e. a single
[real, imaginary] pair).


>
> //Function interfaces behavior - If output array is immutable, operations
> return a copy, else result is applied in place on the passed in output and
> returned
>
> //3 Developer API usage of complex operations on complex arrays
>
> ComplexDoubleArray a = init();
> a = a.asImmutable();
>
> ComplexDoubleArray r1  = a.apply(ComplexFunctions::exp);
>
> ComplexDoubleArray r2  = a.apply(ComplexParrallelStreamFunctions::exp);
>

What are you streaming? ComplexDoubleArray sub-arrays? Would the
ComplexParrallelStreamFunctions class be responsible for creating the
Spliterator for this to control sub-ranges?


>
> ComplexDoubleArray r3  = a.apply(ComplexVectorFunctions::exp);
>
> ComplexDoubleArray r4  = a.apply(ComplexJTransformFunctions::forward_fft);
>
>
> // 4  ComplexFunctions can provide commons C99 reference implementations
> for supported complex operations as static methods that match the
> functional interfaces. ( Refactored methods from existing Complex class).
> Third parties can provide alternate implementations such as parallel stream
> or vector based implementations and used by developers as above.
>
>
> //5 the above functions also reused with existing Complex class?
>
> Complex implements ComplexDouble, ComplexDoubleArray {
>
> @Override
> public int size() {return 1;}
>
> @Override
> double [] toDoubleArray() { . . . }
>
> . . .
>
> //Refactored instance methods of Complex class
> public Complex exp() {
> return apply(ComplexFunctions::exp);
>
> }
> . . .
>
> }
>
> Complex c = Complex.ofCartesian(r,i);
>
> //Backward compatible C99 implementation
> Complex expc = c.exp();
>
> Complex thirdparty_exp = c.apply(SomeThirdPartyFunctions::exp);
>

My concern with this approach is that if we store the minimum of a final
real and imaginary part then any operation will have to:

- create a ComplexDoubleArray for the result
- Write to the ComplexDoubleArray
- Convert the result ComplexDoubleArray back to a Complex

If you look at how this can be used then there is a lot of excess object
overhead here when you wish to write code for complex number computation in
an OO way:
See org.apache.commons.math4.legacy.analysis.solvers.LaguerreSolver

IIUC the reason to have ComplexFunctions operate on arrays is to allow
Vector optimisations. In this case the data would have to be extracted into
a Vector species from a double[]. This would be more easily served
by allowing the ComplexBuffer to be written to a double[]:

DoubleComplexBuffer {
// May be a reference to underlying data, or new allocation
double[] getReal();
// Copied to the provided array
double[] getReal(double[] b);
}

By providing a 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-11 Thread Sumanth Rajkumar
On Sat, Jun 11, 2022, 18:02 Gilles Sadowski  wrote:

> I have a hard time figuring out whether these bits of code are
> intended to become the application developer API...
> What data-structure(s) will be visible (from the application)?
> What will be hidden ("implementation details")?
>

Developer API will look something like this

//1) Static methods to initialize array from external forms

ComplexDoubleArray a = ComplexDoubleArray.fromBuffer(Double Buffer);
ComplexDoubleArray b = ComplexDoubleArray.fromArray(double[]);

ComplexDoubleArray c = ComplexDoubleArray.parseFile(File);


//2)  Methods on Array interface for complex operations. One for each
functional interface type.. unary, binary, scalar operations

@FunctionalInterface
interface ComplexDoubleUnaryOperator {

ComplexDoubleArray apply(ComplexDoubleArray input, ComplexDoubleArray
result);
}

interface ComplexDoubleArray {

int size();

//MutableComplexDoubleArray extends ComplexDoubleArray with setter,
mutation and static methods to allocate capacity

MutableComplexDoubleArray asMutable();

ComplexDoubleArray asImmutable();

default boolean isImmutable() { return true;}


  default ComplexDoubleArray apply(ComplexDoubleUnaryOperator op){

return op.apply(this, result);

}

. . .

}

//Function interfaces behavior - If output array is immutable, operations
return a copy, else result is applied in place on the passed in output and
returned

//3 Developer API usage of complex operations on complex arrays

ComplexDoubleArray a = init();
a = a.asImmutable();

ComplexDoubleArray r1  = a.apply(ComplexFunctions::exp);

ComplexDoubleArray r2  = a.apply(ComplexParrallelStreamFunctions::exp);

ComplexDoubleArray r3  = a.apply(ComplexVectorFunctions::exp);

ComplexDoubleArray r4  = a.apply(ComplexJTransformFunctions::forward_fft);


// 4  ComplexFunctions can provide commons C99 reference implementations
for supported complex operations as static methods that match the
functional interfaces. ( Refactored methods from existing Complex class).
Third parties can provide alternate implementations such as parallel stream
or vector based implementations and used by developers as above.


//5 the above functions also reused with existing Complex class?

Complex implements ComplexDouble, ComplexDoubleArray {

@Override
public int size() {return 1;}

@Override
double [] toDoubleArray() { . . . }

. . .

//Refactored instance methods of Complex class
public Complex exp() {
return apply(ComplexFunctions::exp);

}
. . .

}

Complex c = Complex.ofCartesian(r,i);

//Backward compatible C99 implementation
Complex expc = c.exp();

Complex thirdparty_exp = c.apply(SomeThirdPartyFunctions::exp);

//Require Java16+
Complex vectorexp = c.apply(Complex VectorFunctions::exp)

Thanks,
Sumanth


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-11 Thread Matt Juntunen
Hello,

Good discussion here! This is great!

I lost track of what the overall goal here is while reading through
the conversation. The goal of NUMBERS-186 is to "allow operations to
be performed on lists of complex numbers". My first thought when
looking at this is "how are we going to represent lists of complex
numbers?" I don't think there is a single answer to this since the
correct format for a list of complex numbers is whatever format the
user already has them in. They could be in a file, in separate double
arrays, in a single double array (alternating real and imaginary), in
a float array, in a java.nio.Buffer, etc. So far, I haven't seen an
API that can accomodate all of these. What I would like to see us
create is an interface or abstract class like java.util.Buffer that
allows us to wrap an underlying storage mechanism with complex number
semantics. For example, if you have real and imaginary parts in two
separate arrays, you could do something like

ComplexBuffer buf =
ComplexBuffer.fromRealAndImaginaryArrays(realArr, imArr);

Similarly, with a DoubleBuffer:

ComplexBuffer buf = ComplexBuffer.fromDoubleBuffer(buf);

We can completely hide the classes implementing the wrappings here
from the public API so that things are straightforward for the user.
If we can first create a simple public API like this, then we can
safely focus on performance improvements within the private code.

Regards,
Matt J


On Sat, Jun 11, 2022 at 8:32 AM Gilles Sadowski  wrote:
>
> Hello.
>
> > [...]
> >
> > interface ComplexDoubleArray {
> > Stream stream(int start, int length);
> > }
> >
> > ComplexDoubleArray a;
> > // Will use the Java 8 ForkJoinPool.commonPool() for parallel execution
> > a.stream(start, length).parallel().forEach(x -> ComplexFunctions.conj(x,
> > x));
> >
> > class ComplexFunctions {
> > static void conj(ComplexDoubleArray in, ComplexDoubleArray out);
> > }
> >
> > [...]
>
> I have a hard time figuring out whether these bits of code are
> intended to become the application developer API...
> What data-structure(s) will be visible (from the application)?
> What will be hidden ("implementation details")?
> Do we have use-cases of non-trivial processing of N-dimensional
> cubes of complex numbers?  [I imagine that the same API should
> be able to also process cubes of real numbers (without storing the
> "0" imaginary parts).]
>
> Gilles
>
> -
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-11 Thread Gilles Sadowski
Hello.

> [...]
>
> interface ComplexDoubleArray {
> Stream stream(int start, int length);
> }
>
> ComplexDoubleArray a;
> // Will use the Java 8 ForkJoinPool.commonPool() for parallel execution
> a.stream(start, length).parallel().forEach(x -> ComplexFunctions.conj(x,
> x));
>
> class ComplexFunctions {
> static void conj(ComplexDoubleArray in, ComplexDoubleArray out);
> }
>
> [...]

I have a hard time figuring out whether these bits of code are
intended to become the application developer API...
What data-structure(s) will be visible (from the application)?
What will be hidden ("implementation details")?
Do we have use-cases of non-trivial processing of N-dimensional
cubes of complex numbers?  [I imagine that the same API should
be able to also process cubes of real numbers (without storing the
"0" imaginary parts).]

Gilles

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-11 Thread Alex Herbert
On Sat, 11 Jun 2022 at 07:09, Sumanth Rajkumar 
wrote:

> Hi Alex and Gilles,
>
> For the complex functional interfaces, we have so far been working on
> different options but all operate on single complex numbers one at a
> time...
>
> Instead can we design around Functional Interfaces that work on List/Arrays
> instead?
>

An interesting approach. IIUC this approach is to allow parallel
optimisation. So the question is what computations would be performed in
parallel on a large set of numbers? I am wondering if all the ISO c99
functions would ever be used in this way. And if they are, how well they
would optimise given the high number of branch statements in many of the
functions to handle edge cases. The optimisation is performing:

for i in range:
x(i) = f(x(i))

So you have to provide a function to operate on a number to obtain another
number. How is this coded in the Java Vector API for simd support?

Would a single layer of abstraction mapping a double[] (in the list) to
ComplexNumber (for the function input) and back (from the function output)
impact performance?

<-- SNIP -->

>
> Interface ComplexDoubleArray{
>

> DoubleStream realAndImgPairs (int index, int length)
>
> <-- SNIP -->

A stream would have to have the pair of [real, imag] as the unit that the
stream operates on. It cannot be a (possibly interleaved) stream of each
part otherwise no function can operate on the whole complex number. Any API
would require:

Stream stream(int index, int length)

with T the type of the complex number.

...
>
> }
>
> @FunctionalInterface
> Interface ComplexDoubleUnaryOperator{
>
> void apply(ComplexDoubleArray input, ComplexDoubleArray output, int
> inputoffset, int outputoffset, int length);
>
> }
>
> This has following advantages
>
> 1) iterating implementations over lists will now be in the complex function
> instead of ComplexList data structures allowing for different
> implementations. For example we could have multi threaded java.util.stream
> based operation on lists and single threaded cursor while loop based
> implementation as suggested before by Alex.
>

Thinking about streams...

For multi-threaded stream based operation this would:

- Create the stream with a start and end point
- Create a custom Spliterator holding the range limits
- Allow division of the Spliterator which handles dividing the range until
no more divisions are required (max threads reached)

Thus the final unit to operate on is an unknown range (this is known to the
Spliterator) of numbers. The unit for the functional interface is then
ComplexDoubleArray:

interface ComplexDoubleArray {
Stream stream(int start, int length);
}

ComplexDoubleArray a;
// Will use the Java 8 ForkJoinPool.commonPool() for parallel execution
a.stream(start, length).parallel().forEach(x -> ComplexFunctions.conj(x,
x));

class ComplexFunctions {
static void conj(ComplexDoubleArray in, ComplexDoubleArray out);
}

So for streams the operations are required to operate on a range that is
unknown. Internally the method must then have a way to access each entry of
the ComplexDoubleArray, which is effectively a List.subList(...).

Did you envision a different implementation?


> 2) it will be required to take advantage of simd parallelism as discussed
> before. For example conjugate operation on Complex list (double[] of real
> and imaginary pairs) would be vector multiplication with array [
> 1,-1,1-1,..]
>
> If functional interface enforce operation on one complex number at a time,
> we might not be able take advantage of simd optimizations?
>

IIUC the Java vector API is for multiplications, additions, and other
arithmetic on primitives. The API is not finalised but it appears to have
support for pow and sqrt elementary functions. So this would not allow full
support for the ISO c99 elementary functions in Complex. Also the API
requires a primitive array to be converted to a Vector species and operated
on.

So perhaps to support this only requires that any list of complex numbers
can return the real and imaginary parts:

interface ComplexList {
void getReal(int start, int length, double[] dest);
void getImaginary(int start, int length, double[] dest);
// set methods
}

Then the functions can be written to extract the parts from the list,
operate on them using the Java vector API and return them to the list.

These functions would have an advantage on simple primitive operations. But
any functions that require conditional logic may not be optimised (this is
not clear from the examples I found). So for instance the multiplication of
two complex numbers performed using:

(a + i b)(c + i d) = (ac - bd) + i (ad + bc)

final double ac = a * c;
final double bd = b * d;
final double ad = a * d;
final double bc = b * c;
double x = ac - bd;
double y = ad + bc;

The result x and y are then checked for NaN and suitable infinities
recovered which requires a lot of logic. This logic may have to be moved
out of the vector optimised loop and 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-11 Thread Alex Herbert
On Sat, 11 Jun 2022 at 06:30, Sumanth Rajkumar 
wrote:

> On Fri, Jun 10, 2022, 19:30 Gilles Sadowski  wrote:
>
> > The current implementation of "Complex" encapsulates two "double" fields
> > (not
> > a "double[]").
> > Should we make two, at first separate, discussions: One for the
> > implementation
> > of the "complex number" concept, and another for (n-dimensional) lists of
> > them?
> >
>
> Yes. We could also change existing Complex type from two double fields to
> double[] and even make it implement new ComplexNumber interface? This
> should maintain runtime compatibility?
>

True. It does have the following disadvantages:

- No longer immutable. Immutability would have to be enforced by
encapsulation.
- Increases memory consumption. Note this would compound the original issue
with representing Complex in a List with inefficient memory
consumption. So any application that does not update to the new
implementation would suffer.


>
> I was thinking this would allow efficient reuse of functions processing
> lists also to be used on single numbers (Complex) which is also a list of
> size 1
>

But we have also discussed other ways to share code between a single number
and a list of them that are more safe, i.e. those that represent each entry
of the list as a type to pass to the computation method which stores the
result in the provided computation result.


>
> Jtransform has support for large arrays (size greater than integer.max with
> array index of type long.
>
> Do we need to support that now or add that support later if needed?
>

No. You have to have a very good reason to use the undocumented
sun.misc.Unsafe in code. I do not think we currently have that. Note that
~2^31 is a lot of numbers and to exceed this would be a specialist
application for example using JTransforms 3D FFT on very large 3D data
represented as a 1D array.


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-11 Thread Alex Herbert
On Sat, 11 Jun 2022 at 06:08, Sumanth Rajkumar 
wrote:

>
> The type change would have been source compatible where existing
> applications would have to recompile  (without any code changes) to run
> with the new version?
>

Yes.


>
> So yes, we cannot change Complex type to interface to maintain binary
> runtime compatibility
>
> I assume, binary compatibility would be maintained if we add additional
> interfaces with new methods to Complex class?
>

Yes. To use new methods another application would have to recompile source.
Those applications that do now recompile source are ignorant of any new
methods.


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-11 Thread Sumanth Rajkumar
Hi Alex and Gilles,

For the complex functional interfaces, we have so far been working on
different options but all operate on single complex numbers one at a time...

Instead can we design around Functional Interfaces that work on List/Arrays
instead?

Interface ComplexDoubleArray{

/* Methods for set/get by index as well as set/get  array ranges on
primitive double arrays*/

void set(int index, int sourceIndex, int len, double[] realAndImgPairs)

void get(int index, int destIndex, int len, double[] realAndImgPairs)

void set(int index, ComplexDouble c)

ComplexDouble get(int index)

Iterator iterator( int index, int length)

DoubleStream realAndImgPairs (int index, int length)

...

}

@FunctionalInterface
Interface ComplexDoubleUnaryOperator{

void apply(ComplexDoubleArray input, ComplexDoubleArray output, int
inputoffset, int outputoffset, int length);

}

This has following advantages

1) iterating implementations over lists will now be in the complex function
instead of ComplexList data structures allowing for different
implementations. For example we could have multi threaded java.util.stream
based operation on lists and single threaded cursor while loop based
implementation as suggested before by Alex.

2) it will be required to take advantage of simd parallelism as discussed
before. For example conjugate operation on Complex list (double[] of real
and imaginary pairs) would be vector multiplication with array [
1,-1,1-1,..]

If functional interface enforce operation on one complex number at a time,
we might not be able take advantage of simd optimizations?

3) operation on single complex number is now just operation on list/array
of size 1. We can make existing Complex class implement ComplexDoubleArray
interface



Thanks
Sumanth



On Sat, Jun 11, 2022, 11:00 Sumanth Rajkumar 
wrote:

>
>
> On Fri, Jun 10, 2022, 19:30 Gilles Sadowski  wrote:
>
>> The current implementation of "Complex" encapsulates two "double" fields
>> (not
>> a "double[]").
>> Should we make two, at first separate, discussions: One for the
>> implementation
>> of the "complex number" concept, and another for (n-dimensional) lists of
>> them?
>>
>
> Yes. We could also change existing Complex type from two double fields to
> double[] and even make it implement new ComplexNumber interface? This
> should maintain runtime compatibility?
>
> For the interface, I suggest ComplexDouble (and ComplexFloat) intead of
> ComplexNumber?
>
>
> > A) ComplexCartesianImpl data structure will change to double[]
>> > realAndImgPair
>>
>> What gain do you expect from involving an array here?
>>
>
>  We can make Complex class implement new ComplexList and ComplexNumber
> interface..
>
> I was thinking this would allow efficient reuse of functions processing
> lists also to be used on single numbers (Complex) which is also a list of
> size 1
>
> > B) ComplexList can use single double[] for realAndImg parts (similar to
>> all
>> > external implementations such as jtransform)
>>
>> Yes (because of the gain in RAM usage).
>> But AFAICT, the goal would be to make the "double[]" an "implementation
>> detail" of "ComplexList" and have all operators handle "ComplexList" (or
>> any n-dimensional "cube") as their input/output (?).
>>
>>
> Yes. Also looking at jtransform naming, I suggest ComplexDoubleArray (and
> ComplexFloatArray) instead of ComplexList?
>
> Jtransform has support for large arrays (size greater than integer.max
> with array index of type long.
>
> Do we need to support that now or add that support later if needed?
>
> Thanks
> Sumanth
>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Sumanth Rajkumar
On Fri, Jun 10, 2022, 19:30 Gilles Sadowski  wrote:

> The current implementation of "Complex" encapsulates two "double" fields
> (not
> a "double[]").
> Should we make two, at first separate, discussions: One for the
> implementation
> of the "complex number" concept, and another for (n-dimensional) lists of
> them?
>

Yes. We could also change existing Complex type from two double fields to
double[] and even make it implement new ComplexNumber interface? This
should maintain runtime compatibility?

For the interface, I suggest ComplexDouble (and ComplexFloat) intead of
ComplexNumber?


> A) ComplexCartesianImpl data structure will change to double[]
> > realAndImgPair
>
> What gain do you expect from involving an array here?
>

 We can make Complex class implement new ComplexList and ComplexNumber
interface..

I was thinking this would allow efficient reuse of functions processing
lists also to be used on single numbers (Complex) which is also a list of
size 1

> B) ComplexList can use single double[] for realAndImg parts (similar to
> all
> > external implementations such as jtransform)
>
> Yes (because of the gain in RAM usage).
> But AFAICT, the goal would be to make the "double[]" an "implementation
> detail" of "ComplexList" and have all operators handle "ComplexList" (or
> any n-dimensional "cube") as their input/output (?).
>
>
Yes. Also looking at jtransform naming, I suggest ComplexDoubleArray (and
ComplexFloatArray) instead of ComplexList?

Jtransform has support for large arrays (size greater than integer.max with
array index of type long.

Do we need to support that now or add that support later if needed?

Thanks
Sumanth


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Sumanth Rajkumar
Thanks for the detailed explanation with example. Now I understand the
difference between binary vs source backward compatibility.

The type change would have been source compatible where existing
applications would have to recompile  (without any code changes) to run
with the new version?

So yes, we cannot change Complex type to interface to maintain binary
runtime compatibility

I assume, binary compatibility would be maintained if we add additional
interfaces with new methods to Complex class?

For example, we should be ok if we add  a new ComplexDouble interface with
possibly new methods to Complex class?



On Fri, Jun 10, 2022, 20:45 Alex Herbert  wrote:

>
> > These are expected changes... Is there a compatibility issue here?
> >
>
> Yes. These are reported as errors.
>
> This is the main issue:
>
> https://revapi.org/revapi-java/differences.html#java.class.kindChanged
>
> Changing a class to an interface. In this case methods on the object are
> invoked using a different instruction.
>

So if you change class A to an interface then Test will have a runtime
> linkage error as it cannot find the method
>

Thus we have to keep Complex as a class.
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Alex Herbert
On Fri, 10 Jun 2022 at 14:10, Sumanth Rajkumar 
wrote:

> For 1) I ran mvn verify and found the following errors
>
>
> org.apache.commons.numbers.complex.Complex.getImaginary():METHOD_NOW_ABSTRACT,
> org.apache.commons.numbers.complex.Complex.getReal():METHOD_NOW_ABSTRACT,
> org.apache.commons.numbers.complex.Complex:CLASS_NOW_ABSTRACT,
> org.apache.commons.numbers.complex.Complex:CLASS_TYPE_CHANGED,
>
> org.apache.commons.numbers.complex.ComplexCartesianImpl:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE,
>
> org.apache.commons.numbers.complex.ComplexList:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE,
>
> org.apache.commons.numbers.complex.ImmutableComplexList:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE
>
> These are expected changes... Is there a compatibility issue here?
>

Yes. These are reported as errors.

One point here is that Complex is a final class. So some of the errors
regarding inheritance are non-issues. However binary compatibility requires
that a class compiled against the old version can run against the new one.
The main issue is changing a class to an interface (type change).

The japicmp plugin does not have a lot of documentation. You can try revapi
instead. Put this in the plugins section of the pom.xml:

  
org.revapi
revapi-maven-plugin
0.14.6

  
org.revapi
revapi-java
0.26.1
  

  

Then run:

mvn revapi:check  (if you have the jar package)
mvn package revapi:check -DskipTests -Djavadoc.skip  (if you don't)

This will output some similar compatibility errors and link to online
documentation that explains why it is a problem.

This is the main issue:

https://revapi.org/revapi-java/differences.html#java.class.kindChanged

Changing a class to an interface. In this case methods on the object are
invoked using a different instruction.

Save this as Test.java:

public class Test {
  static class A {
public int getAnswer() { return 42; }
  }

  interface B {
int getAnswer();
  }

  static class Bimp implements B {
public int getAnswer() { return 13; }
  }

  public static void main(String[] args) {
A a = new A();
System.out.println(a.getAnswer());
B b = new Bimp();
System.out.println(b.getAnswer());
  }
}

> javac Test.java
> java Test
42
13
> javap -c Test
...

12: invokevirtual #16 // Method Test$A.getAnswer:()I
...

30: invokeinterface #29,  1   // InterfaceMethod
Test$B.getAnswer:()I
...

Here we see the interface method uses 'invokeinterface' and the class
method uses 'invokevirtual'.

So if you change class A to an interface then Test will have a runtime
linkage error as it cannot find the method (this is all assuming that A, B
and Bimp are in their own class files which I didn't do here for
simplicity). Basically if a class thinks the object with a method is a
class and it is changed on the classpath at runtime to an interface this
will not work.


Thus we have to keep Complex as a class. However it does not mean the
methods cannot be moved to e.g.

public final class ComplexFunctions {
interface ComplexResult {
R accept(double real, double imag);
}

public static  R conj(double real, double imaginary,
ComplexResult result) {
return result.accept(real, -imaginary);
}
}

And Complex changed to e.g:

ComplexFunctions conj() {
return ComplexMath.conj(real(), imag(), Complex::ofCartesian);
}


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Gilles Sadowski
Hello.

Le ven. 10 juin 2022 à 15:10, Sumanth Rajkumar
 a écrit :
>
> For 1) I ran mvn verify and found the following errors
>
> org.apache.commons.numbers.complex.Complex.getImaginary():METHOD_NOW_ABSTRACT,
> org.apache.commons.numbers.complex.Complex.getReal():METHOD_NOW_ABSTRACT,
> org.apache.commons.numbers.complex.Complex:CLASS_NOW_ABSTRACT,
> org.apache.commons.numbers.complex.Complex:CLASS_TYPE_CHANGED,
> org.apache.commons.numbers.complex.ComplexCartesianImpl:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE,
> org.apache.commons.numbers.complex.ComplexList:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE,
> org.apache.commons.numbers.complex.ImmutableComplexList:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE
>
> These are expected changes... Is there a compatibility issue here?
>
> 2) Regarding usage of arrays in functional interfaces
> @FunctionalInterface
> public interface ComplexFunction3 {
>   void apply(Complex input, int offset, double[] result);
> }
>
> The underlying implementations of Complex and ComplexList all use arrays
> and there would be no additional array instantiation /RAM allocation just
> to apply the functional interface functions

The current implementation of "Complex" encapsulates two "double" fields (not
a "double[]").
Should we make two, at first separate, discussions: One for the implementation
of the "complex number" concept, and another for (n-dimensional) lists of them?

> A) ComplexCartesianImpl data structure will change to double[]
> realAndImgPair

What gain do you expect from involving an array here?

> B) ComplexList can use single double[] for realAndImg parts (similar to all
> external implementations such as jtransform)

Yes (because of the gain in RAM usage).
But AFAICT, the goal would be to make the "double[]" an "implementation
detail" of "ComplexList" and have all operators handle "ComplexList" (or
any n-dimensional "cube") as their input/output (?).

Regards,
Gilles

>
> Thanks
> Sumanth
>
> On Fri, 10 Jun 2022 at 08:58, Gilles Sadowski  wrote:
>
> > Hello.
> >
> > Le ven. 10 juin 2022 à 14:43, Sumanth Rajkumar
> >  a écrit :
> > >
> > > 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();
> > >  }
> >
> > My first feeling would be to steer away from (ab)using array as a pair.
> > We may have to use arrays for interfacing with external tools (or perhaps
> > internally too, e.g. to minimize RAM usage when processing a large list
> > of complex numbers) but from a OO point of view, we should come up
> > with an encapsulation that ensures robustness (e.g. featuring
> > immutability).
> > Also the type(s) should be easily usable in functional programming style.
> >
> > Gilles
> >
> > >
> > > [...]

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Sumanth Rajkumar
For 1) I ran mvn verify and found the following errors

org.apache.commons.numbers.complex.Complex.getImaginary():METHOD_NOW_ABSTRACT,
org.apache.commons.numbers.complex.Complex.getReal():METHOD_NOW_ABSTRACT,
org.apache.commons.numbers.complex.Complex:CLASS_NOW_ABSTRACT,
org.apache.commons.numbers.complex.Complex:CLASS_TYPE_CHANGED,
org.apache.commons.numbers.complex.ComplexCartesianImpl:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE,
org.apache.commons.numbers.complex.ComplexList:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE,
org.apache.commons.numbers.complex.ImmutableComplexList:METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE

These are expected changes... Is there a compatibility issue here?

2) Regarding usage of arrays in functional interfaces
@FunctionalInterface
public interface ComplexFunction3 {
  void apply(Complex input, int offset, double[] result);
}

The underlying implementations of Complex and ComplexList all use arrays
and there would be no additional array instantiation /RAM allocation just
to apply the functional interface functions

A) ComplexCartesianImpl data structure will change to double[]
realAndImgPair
B) ComplexList can use single double[] for realAndImg parts (similar to all
external implementations such as jtransform)

Thanks
Sumanth

On Fri, 10 Jun 2022 at 08:58, Gilles Sadowski  wrote:

> Hello.
>
> Le ven. 10 juin 2022 à 14:43, Sumanth Rajkumar
>  a écrit :
> >
> > 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();
> >  }
>
> My first feeling would be to steer away from (ab)using array as a pair.
> We may have to use arrays for interfacing with external tools (or perhaps
> internally too, e.g. to minimize RAM usage when processing a large list
> of complex numbers) but from a OO point of view, we should come up
> with an encapsulation that ensures robustness (e.g. featuring
> immutability).
> Also the type(s) should be easily usable in functional programming style.
>
> Gilles
>
> >
> > [...]
>
> -
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Gilles Sadowski
Hello.

Le ven. 10 juin 2022 à 14:43, Sumanth Rajkumar
 a écrit :
>
> 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();
>  }

My first feeling would be to steer away from (ab)using array as a pair.
We may have to use arrays for interfacing with external tools (or perhaps
internally too, e.g. to minimize RAM usage when processing a large list
of complex numbers) but from a OO point of view, we should come up
with an encapsulation that ensures robustness (e.g. featuring
immutability).
Also the type(s) should be easily usable in functional programming style.

Gilles

>
> [...]

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Gilles Sadowski
Hello.

> [...]
>
> >
> > We could split complex unary operators into two primitive functions (
> > ToDoubleFunction) one returning the real part of result and other
> > for imaginary part
> >
> > interface ComplexFunction  {
> >  ToDoubleFunction getReal() ;
> >  ToDoubleFunction getImaginary() ;
> > }
> >
> >
> This has concerns for efficiency.

First thought that came to my mind, being confirmed when looking
at the "conj" example (where "applyAsDouble" is called twice)...

Gilles

> [...]

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Sumanth Rajkumar
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 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  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  >
> 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) one returning the real part of result and
> other
> > for imaginary part
> >
> > interface ComplexFunction  {
> >  ToDoubleFunction getReal() ;
> >  ToDoubleFunction 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 getReal() {
> > return complex -> complex.real();
> > }
> > @Override
> > public ToDoubleFunction 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 realFunc = fun.getReal();
> > ToDoubleFunction 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?
> >
>
> 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
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Alex Herbert
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 
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) one returning the real part of result and other
> for imaginary part
>
> interface ComplexFunction  {
>  ToDoubleFunction getReal() ;
>  ToDoubleFunction 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 getReal() {
> return complex -> complex.real();
> }
> @Override
> public ToDoubleFunction 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 realFunc = fun.getReal();
> ToDoubleFunction 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?
>

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


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Sumanth Rajkumar
2) ComplexFunction and ComplexResult functional interfaces
Following up on my previous email, another alternative for ComplexFunction
without using generic ComplexResult is as follows

@FunctionalInterface
public interface ComplexFunction3 {
  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 {
..
// applies changes in place
void forEach(ComplexFunction fun) {

ComplexCursor cursor = new ComplexCursor();
while (cursor.index < r.length) {
cursor.apply(realFunc.applyAsDouble(cursor),
imgFunc .applyAsDouble(cursor));
cursor.index++;
}
}
...
}



On Fri, 10 Jun 2022 at 07:55, Sumanth Rajkumar 
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
>
>
> https://github.com/sumanth-rajkumar/commons-numbers/blob/sumanth-gsoc-22/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
>
> https://github.com/sumanth-rajkumar/commons-numbers/blob/sumanth-gsoc-22/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexCartesianImpl.java
>
> This I assume should meet the backward compatibility requirements?
>
> The proposed functional interface changes introduces a new interface
> ComplexNumber.
> I think we could reuse the refactored Complex interface instead of  a new
> ComplexNumber interface and still maintain full backward compatibility.
>
> This would provide flexibility to older applications to work with new
> implementations of Complex such as MutableComplexImpl or ComplexPolarImpl
> or even ComplexStructImpl in the future whenever Java supports value types.
>
> Please let me know what you think.
>
> 2) ComplexFunction and ComplexResult functional interfaces
> Yes the generic  type introduces noise and can be solved as you
> suggested.
>
> I was also thinking about an alternative that avoids the ComplexResult and
> the generic type .
>
> We could split complex unary operators into two primitive functions (
> ToDoubleFunction) one returning the real part of result and other
> for imaginary part
>
> interface ComplexFunction  {
>  ToDoubleFunction getReal() ;
>  ToDoubleFunction getImaginary() ;
> }
>
> And for example the Conjugate implementation would look like this
> ComplexFunction conj = new ComplexFunction2() {
> @Override
> public ToDoubleFunction getReal() {
> return complex -> complex.real();
> }
> @Override
> public ToDoubleFunction getImaginary() {
> return complex -> -complex.imag();
> }
>
> };
>};
>
> 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 realFunc = fun.getReal();
> ToDoubleFunction 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?
>
>
> 3) Naming convention for the Functional Interfaces
>
> On reviewing the functions in java.util.functions package, the convention
> is
>  "Function" name is used for interfaces that can accept inputs of
> different types and return result of different type
>  "Operator" are 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-06-10 Thread Sumanth Rajkumar
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

https://github.com/sumanth-rajkumar/commons-numbers/blob/sumanth-gsoc-22/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/Complex.java
https://github.com/sumanth-rajkumar/commons-numbers/blob/sumanth-gsoc-22/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexCartesianImpl.java

This I assume should meet the backward compatibility requirements?

The proposed functional interface changes introduces a new interface
ComplexNumber.
I think we could reuse the refactored Complex interface instead of  a new
ComplexNumber interface and still maintain full backward compatibility.

This would provide flexibility to older applications to work with new
implementations of Complex such as MutableComplexImpl or ComplexPolarImpl
or even ComplexStructImpl in the future whenever Java supports value types.

Please let me know what you think.

2) ComplexFunction and ComplexResult functional interfaces
Yes the generic  type introduces noise and can be solved as you
suggested.

I was also thinking about an alternative that avoids the ComplexResult and
the generic type .

We could split complex unary operators into two primitive functions (
ToDoubleFunction) one returning the real part of result and other
for imaginary part

interface ComplexFunction  {
 ToDoubleFunction getReal() ;
 ToDoubleFunction getImaginary() ;
}

And for example the Conjugate implementation would look like this
ComplexFunction conj = new ComplexFunction2() {
@Override
public ToDoubleFunction getReal() {
return complex -> complex.real();
}
@Override
public ToDoubleFunction getImaginary() {
return complex -> -complex.imag();
}

};
   };

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 realFunc = fun.getReal();
ToDoubleFunction 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?


3) Naming convention for the Functional Interfaces

On reviewing the functions in java.util.functions package, the convention
is
 "Function" name is used for interfaces that can accept inputs of
different types and return result of different type
 "Operator" are specialization of "Function" that take same type for
all inputs and result

Should we follow a similar naming convention for Complex functional
interfaces?

Thanks




On Fri, 27 May 2022 at 21:34, Alex Herbert  wrote:

> On Thu, 26 May 2022 at 15:04, Gilles Sadowski 
> wrote:
>
> >
> > > Next, I wanted to mention how I plan to start this project and was
> hoping
> > > to get some feedback.
> > >
> > > As per my proposal, the first thing I wanted to start with was the API
> > > design which would have interfaces to represent complex numbers,
> methods
> > to
> > > convert to/from linear primitive arrays, Java 8 functional interfaces
> for
> > > unary/binary operators and for functions for complex operations and
> > > transforms involving: complex number and real numbers, complex vectors
> > and
> > > scalars, complex matrix, vectors and scalars.
> >
>
> There are many items here. I would suggest breaking it down. Perhaps:
>
> 1.
> interfaces to represent complex numbers
> unary/binary operators and for functions for complex operations
>
> 2.
> methods to convert to/from linear primitive arrays
>
> 3.
> complex vectors and scalars, complex matrix, vectors and scalars.
>
>
> Although not completely independant, we could discuss each in turn and see
> what functionality is required.
>
> I will start with topic 1. Currently we have a single object, Complex, that
> represents a complex number in cartesian form. It has a full set of
> operations specified in ISO C99. I would suggest you have a look at the
> specification as it has a lot of information 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-05-27 Thread Alex Herbert
On Thu, 26 May 2022 at 15:04, Gilles Sadowski  wrote:

>
> > Next, I wanted to mention how I plan to start this project and was hoping
> > to get some feedback.
> >
> > As per my proposal, the first thing I wanted to start with was the API
> > design which would have interfaces to represent complex numbers, methods
> to
> > convert to/from linear primitive arrays, Java 8 functional interfaces for
> > unary/binary operators and for functions for complex operations and
> > transforms involving: complex number and real numbers, complex vectors
> and
> > scalars, complex matrix, vectors and scalars.
>

There are many items here. I would suggest breaking it down. Perhaps:

1.
interfaces to represent complex numbers
unary/binary operators and for functions for complex operations

2.
methods to convert to/from linear primitive arrays

3.
complex vectors and scalars, complex matrix, vectors and scalars.


Although not completely independant, we could discuss each in turn and see
what functionality is required.

I will start with topic 1. Currently we have a single object, Complex, that
represents a complex number in cartesian form. It has a full set of
operations specified in ISO C99. I would suggest you have a look at the
specification as it has a lot of information about this [1].

There is a benchmark for these operations in the examples JMH module:
org.apache.commons.numbers.examples.jmh.complex.ComplexPerformance

Ideally any changes to extract all the methods into a static class should
not impact performance. Many of the methods are quite involved and
therefore slow. However some methods such as those for
add/subtract/multiply/divide with real or imaginary scalars will be fast.
It would be interesting to see if abstraction to a static class impacts
their performance. These operations are not in the JMH benchmark so this
could be added to provide a reference point for these.


>From your GH code you have the following interface:

public interface ComplexFunction {
 R apply(double r, double i, ComplexResult result);
}

I cannot create a lambda function for this as the method has a generic type
parameter. This fails to compile.

ComplexFunction f = (r, i, result) -> {
// conjugate
return result.apply(r, -i);
};

This can be solved by moving  to the interface declaration:

public interface ComplexFunction {
R apply(double r, double i, ComplexResult result);
}

But then all use of ComplexFunction has to be typed which can get noisy. It
is however explicit in what the function output will be (and we assume the
input is a complex number of some sort).


Q. Do we wish to support effectively duplication of operations by accepting
primitives and also a ComplexNumber type in the static methods:

interface ComplexNumber {
double real();
double imag();
}

class ComplexFunctions {
 R sin(ComplexNumber c, ComplexResult r) {
return sin(c.real(), c.imag(), r);
}
 R sin(double r, double i, ComplexResult) {
// ...
}
}

There are various options for chaining methods together for sequential
operations on the same complex. Should this avoid repeat object allocation
by providing a MutableComplex holder:

class MutableComplex implements ComplexNumber,
ComplexResult {
   // allows read, write   from/to  real, imaginary parts
}



Q. How to manipulate ComplexList:

class ComplexList implements List {
private double[] r;
private double[] i;
}

You have forEach methods (note this is without the type parameter):

void forEach(ComplexFunction fun);

So how do I declare a function to pass to the list, that accepts the real
and imaginary parts and saves them back to the list. Currently you have the
ComplexFunction accept the real and imaginary parts. But what if it
accepted a ComplexNumber:

public interface ComplexFunction {
R apply(ComplexNumber c, ComplexResult result);
}


The ComplexList need only provide a single object that acts as a read/write
cursor over the data by implementing both interfaces ComplexNumber and
ComplexResult:

// Internal class
class ComplexCursor implements ComplexNumber, ComplexResult {
// Directly manipulated by the enclosing list
int index;

@Override
public Void apply(double r, double i) {
ComplexList.this.r[index] = r;
ComplexList.this.i[index] = i;
return null;
}

@Override
public double real() {
return ComplexList.this.r[index];
}

@Override
public double imag() {
return ComplexList.this.i[index];
}
}

I can write the method:

void forEach(ComplexFunction fun) {
ComplexCursor cursor = new ComplexCursor();
while (cursor.index < r.length) {
fun.apply(cursor, cursor);
cursor.index++;
}
}

And call it like this:

class ComplexFunctions {
static  R conj(ComplexNumber c, ComplexResult r) {
return r.apply(c.real(), -c.imag());
}
}


ComplexList l;
l.forEach(ComplexFunctions::conj);

// Using a lambda
l.forEach((c, 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-05-26 Thread Gilles Sadowski
Hello.

Le jeu. 26 mai 2022 à 07:04, Sumanth Rajkumar
 a écrit :
>
> Hi,
>
> My proposal was accepted into GSoC 2022 to work on the Numbers-186 [1] Jira
> of the Commons Numbers project.
>
> I first want to ask if I can be assigned to this Jira

Done.

> since my GSoC
> proposal was accepted.
>
> Next, I wanted to mention how I plan to start this project and was hoping
> to get some feedback.
>
> As per my proposal, the first thing I wanted to start with was the API
> design which would have interfaces to represent complex numbers, methods to
> convert to/from linear primitive arrays, Java 8 functional interfaces for
> unary/binary operators and for functions for complex operations and
> transforms involving: complex number and real numbers, complex vectors and
> scalars, complex matrix, vectors and scalars.

For each of the mentioned functionalities, types and operations,
please provide a concrete example of what you propose, indicating
whether it is a new feature or a change and whethe it is backwards
comptable (BC) or not.  [These details can be further discussed on
the JIRA page.]

Whenever possible, please ensure that the proposed changes do
not break the build.  [You can test this by opening a PR, which should
trigger an automated build.]

>
> Working on the API, am I on the right track to start with refactoring all
> the existing methods in the Complex class as static functions for use as
> lambdas?
>
> I already refactored some methods which can be viewed here [2]

Renaming is typically something to be first discussed here and/or
on JIRA.
Unless other non BC changes are foreseen for the next release,
such "cosmetic" changes must be avoided.

Thanks,
Gilles

>
> Thanks,
>
> Sumanth
>
> [1] https://issues.apache.org/jira/browse/NUMBERS-186
>
> [2]
> https://github.com/sumanth-rajkumar/commons-numbers/tree/sumanth-gsoc-22/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex
>
> On Mon, Mar 28, 2022, 7:01 PM Gilles Sadowski  wrote:
>
> > Hello.
> >
> > Le lun. 28 mars 2022 à 00:32, Sumanth Rajkumar
> >  a écrit :
> > >
> > > Thanks Alex and Gilles for your feedback
> > >
> > > So currently Commons Math transform depends on Common complex numbers,
> > and
> > > the API involves usage of Complex Object Arrays instead of primitive
> > array
> > > data structures
> > >
> > > I also briefly looked into other library implementations besides
> > Jtransform
> > > and EJML that are not pure java but have java bindings such as JBLAS[1]
> > and
> > > NAG[2]
> > > All of the implementation use single array data structures to represent
> > > Complex Lists and higher dimensional matrices
> > >
> > > Since these involve parallel data pipelines I looked into libraries that
> > > use SIMD [3] operations that use GP GPU (jcuda [4][5] /aparapi [6]) and
> > CPU
> > > (Java 17 Vector API [7])
> >
> > Thanks for the investigation!
> >
> > >
> > > Given all the alternative implementations, I agree it does not make sense
> > > to re implement transforms here.
> >
> > Some transforms are (already) implemented here.
> > Of course, it makes sense to wonder whether to keep maintaining those
> > codes, or rely on external dependencies.  The decision would depend on
> > performance comparisons and whether users are able (or allowed) to
> > interface with native libraries.  [I know of one project where "pure Java"
> > was a requirement...]
> >
> > >
> > > So instead would it be useful to provide users with
> > > 1) a complex numbers Linear Algebra and transforms API to compile against
> > > and run with any of existing providers (apache commons, jtransform, EJML,
> > > jblas)
> > > AND
> > > 2) a service provider interface to allow adapter implementations to
> > > integrate existing and future providers such as jcudas/aparapi/vector
> > APIs
> > >
> > > Do the commons library modularization dependency requirements apply to
> > > compile time dependencies only or runtime also?
> >
> > Which "dependency requirements" are you referring to?
> >
> > > To minimize bloat, the runtime dependencies could be made optional and
> > need
> > > not be transitively included by default
> >
> > Flexibility would be ideal, indeed.
> >
> > >
> > > Providing a Complex linear algebra and transforms API that can run with
> > > different runtime providers would allow users to take advantage of
> > hardware
> > > capabilities and gracefully fallback to reference implementations
> > > It could allow users to take advantage of Java 17 Vector APIs when
> > > available without refactoring their existing libraries
> >
> > That looks great.
> >
> > >
> > > Also do the Apache projects/ license allow for integration with non
> > Apache
> > > software (jtransform /jblas do not use Apache license, jcuda uses MIT
> > > license) ?
> >
> > Licence issues are detailed here:
> >   https://www.apache.org/legal/resolved.html
> >
> > Best regards,
> > Gilles
> >
> > >
> > > Thanks
> > > Sumanth
> > >
> > > [1] http://jblas.org/
> > >
> > > [2]
> > 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-05-25 Thread Sumanth Rajkumar
Hi,

My proposal was accepted into GSoC 2022 to work on the Numbers-186 [1] Jira
of the Commons Numbers project.

I first want to ask if I can be assigned to this Jira since my GSoC
proposal was accepted.

Next, I wanted to mention how I plan to start this project and was hoping
to get some feedback.

As per my proposal, the first thing I wanted to start with was the API
design which would have interfaces to represent complex numbers, methods to
convert to/from linear primitive arrays, Java 8 functional interfaces for
unary/binary operators and for functions for complex operations and
transforms involving: complex number and real numbers, complex vectors and
scalars, complex matrix, vectors and scalars.


Working on the API, am I on the right track to start with refactoring all
the existing methods in the Complex class as static functions for use as
lambdas?

I already refactored some methods which can be viewed here [2]

Thanks,

Sumanth

[1] https://issues.apache.org/jira/browse/NUMBERS-186

[2]
https://github.com/sumanth-rajkumar/commons-numbers/tree/sumanth-gsoc-22/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex

On Mon, Mar 28, 2022, 7:01 PM Gilles Sadowski  wrote:

> Hello.
>
> Le lun. 28 mars 2022 à 00:32, Sumanth Rajkumar
>  a écrit :
> >
> > Thanks Alex and Gilles for your feedback
> >
> > So currently Commons Math transform depends on Common complex numbers,
> and
> > the API involves usage of Complex Object Arrays instead of primitive
> array
> > data structures
> >
> > I also briefly looked into other library implementations besides
> Jtransform
> > and EJML that are not pure java but have java bindings such as JBLAS[1]
> and
> > NAG[2]
> > All of the implementation use single array data structures to represent
> > Complex Lists and higher dimensional matrices
> >
> > Since these involve parallel data pipelines I looked into libraries that
> > use SIMD [3] operations that use GP GPU (jcuda [4][5] /aparapi [6]) and
> CPU
> > (Java 17 Vector API [7])
>
> Thanks for the investigation!
>
> >
> > Given all the alternative implementations, I agree it does not make sense
> > to re implement transforms here.
>
> Some transforms are (already) implemented here.
> Of course, it makes sense to wonder whether to keep maintaining those
> codes, or rely on external dependencies.  The decision would depend on
> performance comparisons and whether users are able (or allowed) to
> interface with native libraries.  [I know of one project where "pure Java"
> was a requirement...]
>
> >
> > So instead would it be useful to provide users with
> > 1) a complex numbers Linear Algebra and transforms API to compile against
> > and run with any of existing providers (apache commons, jtransform, EJML,
> > jblas)
> > AND
> > 2) a service provider interface to allow adapter implementations to
> > integrate existing and future providers such as jcudas/aparapi/vector
> APIs
> >
> > Do the commons library modularization dependency requirements apply to
> > compile time dependencies only or runtime also?
>
> Which "dependency requirements" are you referring to?
>
> > To minimize bloat, the runtime dependencies could be made optional and
> need
> > not be transitively included by default
>
> Flexibility would be ideal, indeed.
>
> >
> > Providing a Complex linear algebra and transforms API that can run with
> > different runtime providers would allow users to take advantage of
> hardware
> > capabilities and gracefully fallback to reference implementations
> > It could allow users to take advantage of Java 17 Vector APIs when
> > available without refactoring their existing libraries
>
> That looks great.
>
> >
> > Also do the Apache projects/ license allow for integration with non
> Apache
> > software (jtransform /jblas do not use Apache license, jcuda uses MIT
> > license) ?
>
> Licence issues are detailed here:
>   https://www.apache.org/legal/resolved.html
>
> Best regards,
> Gilles
>
> >
> > Thanks
> > Sumanth
> >
> > [1] http://jblas.org/
> >
> > [2]
> https://www.nag.com/numeric/nl/nagdoc_latest/clhtml/c06/c06conts.html
> >
> > [3]
> https://blogs.oracle.com/javamagazine/post/programming-the-gpu-in-java
> >
> > [4] http://jcuda.org/jcuda/jcufft/JCufft.html
> >
> > [5]
> >
> https://github.com/jcuda/jcuda-samples/tree/master/JCudaSamples/src/main/java/jcuda/jcufft/samples
> >
> > [6] http://aparapi.github.io/
> >
> > [7] https://openjdk.java.net/jeps/414
> >
> >
> > On Tue, 22 Mar 2022 at 10:07, Gilles Sadowski 
> wrote:
> >
> > > Hello.
> > >
> > > > [...]
> > > > >
> > > > > Are we expecting complex-numbers to be an efficient pure java
> library
> > > that
> > > > > could be used by other java libraries such as commons-imaging for
> data
> > > > > compression (DCT /JPEG lossy compression)?
> > > > >
> > > >
> > > > Numbers should be seen as a toolbox to be used by other Java
> > > applications.
> > > > The best location for routines is something to discuss on the mailing
> > > list.
> > > > In 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-03-28 Thread Gilles Sadowski
Hello.

Le lun. 28 mars 2022 à 00:32, Sumanth Rajkumar
 a écrit :
>
> Thanks Alex and Gilles for your feedback
>
> So currently Commons Math transform depends on Common complex numbers, and
> the API involves usage of Complex Object Arrays instead of primitive array
> data structures
>
> I also briefly looked into other library implementations besides Jtransform
> and EJML that are not pure java but have java bindings such as JBLAS[1] and
> NAG[2]
> All of the implementation use single array data structures to represent
> Complex Lists and higher dimensional matrices
>
> Since these involve parallel data pipelines I looked into libraries that
> use SIMD [3] operations that use GP GPU (jcuda [4][5] /aparapi [6]) and CPU
> (Java 17 Vector API [7])

Thanks for the investigation!

>
> Given all the alternative implementations, I agree it does not make sense
> to re implement transforms here.

Some transforms are (already) implemented here.
Of course, it makes sense to wonder whether to keep maintaining those
codes, or rely on external dependencies.  The decision would depend on
performance comparisons and whether users are able (or allowed) to
interface with native libraries.  [I know of one project where "pure Java"
was a requirement...]

>
> So instead would it be useful to provide users with
> 1) a complex numbers Linear Algebra and transforms API to compile against
> and run with any of existing providers (apache commons, jtransform, EJML,
> jblas)
> AND
> 2) a service provider interface to allow adapter implementations to
> integrate existing and future providers such as jcudas/aparapi/vector APIs
>
> Do the commons library modularization dependency requirements apply to
> compile time dependencies only or runtime also?

Which "dependency requirements" are you referring to?

> To minimize bloat, the runtime dependencies could be made optional and need
> not be transitively included by default

Flexibility would be ideal, indeed.

>
> Providing a Complex linear algebra and transforms API that can run with
> different runtime providers would allow users to take advantage of hardware
> capabilities and gracefully fallback to reference implementations
> It could allow users to take advantage of Java 17 Vector APIs when
> available without refactoring their existing libraries

That looks great.

>
> Also do the Apache projects/ license allow for integration with non Apache
> software (jtransform /jblas do not use Apache license, jcuda uses MIT
> license) ?

Licence issues are detailed here:
  https://www.apache.org/legal/resolved.html

Best regards,
Gilles

>
> Thanks
> Sumanth
>
> [1] http://jblas.org/
>
> [2] https://www.nag.com/numeric/nl/nagdoc_latest/clhtml/c06/c06conts.html
>
> [3] https://blogs.oracle.com/javamagazine/post/programming-the-gpu-in-java
>
> [4] http://jcuda.org/jcuda/jcufft/JCufft.html
>
> [5]
> https://github.com/jcuda/jcuda-samples/tree/master/JCudaSamples/src/main/java/jcuda/jcufft/samples
>
> [6] http://aparapi.github.io/
>
> [7] https://openjdk.java.net/jeps/414
>
>
> On Tue, 22 Mar 2022 at 10:07, Gilles Sadowski  wrote:
>
> > Hello.
> >
> > > [...]
> > > >
> > > > Are we expecting complex-numbers to be an efficient pure java library
> > that
> > > > could be used by other java libraries such as commons-imaging for data
> > > > compression (DCT /JPEG lossy compression)?
> > > >
> > >
> > > Numbers should be seen as a toolbox to be used by other Java
> > applications.
> > > The best location for routines is something to discuss on the mailing
> > list.
> > > In the example of DCT, I am not aware if imaging currently has an encoder
> > > implementation for this. There is a decoder:
> > > org/apache/commons/imaging/formats/jpeg/decoder/Dct.jav
> >
> > Also:
> >
> > https://gitbox.apache.org/repos/asf?p=commons-math.git;a=blob;f=commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java
> >
> > It would be a maintenance boon if "Commons" could come up with
> > a consensus about which components must be dependency-free and
> > which could depend on other (lower-level) "Commons" components.
> >
> > [Imaging] is clearly higher-level than [Math] and that such non-obvious
> > algorithms should be maintained in a single place.  Through the process
> > of modularizing [Math], we have "commons-math-transform" module,
> > with zero dependency, so it would bring zero bloat to [Imaging] users if
> > we consolidate usage.
> >
> > Of course, that would imply testing and benchmarking all current
> > implementations, and retain the best (taking various axes into account:
> > performance, robustness, flexibility).
> >
> > Regards,
> > Gilles
> >
> > > [...]

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-03-27 Thread Sumanth Rajkumar
Thanks Alex and Gilles for your feedback

So currently Commons Math transform depends on Common complex numbers, and
the API involves usage of Complex Object Arrays instead of primitive array
data structures

I also briefly looked into other library implementations besides Jtransform
and EJML that are not pure java but have java bindings such as JBLAS[1] and
NAG[2]
All of the implementation use single array data structures to represent
Complex Lists and higher dimensional matrices

Since these involve parallel data pipelines I looked into libraries that
use SIMD [3] operations that use GP GPU (jcuda [4][5] /aparapi [6]) and CPU
(Java 17 Vector API [7])

Given all the alternative implementations, I agree it does not make sense
to re implement transforms here.

So instead would it be useful to provide users with
1) a complex numbers Linear Algebra and transforms API to compile against
and run with any of existing providers (apache commons, jtransform, EJML,
jblas)
AND
2) a service provider interface to allow adapter implementations to
integrate existing and future providers such as jcudas/aparapi/vector APIs

Do the commons library modularization dependency requirements apply to
compile time dependencies only or runtime also?
To minimize bloat, the runtime dependencies could be made optional and need
not be transitively included by default

Providing a Complex linear algebra and transforms API that can run with
different runtime providers would allow users to take advantage of hardware
capabilities and gracefully fallback to reference implementations
It could allow users to take advantage of Java 17 Vector APIs when
available without refactoring their existing libraries

Also do the Apache projects/ license allow for integration with non Apache
software (jtransform /jblas do not use Apache license, jcuda uses MIT
license) ?

Thanks
Sumanth

[1] http://jblas.org/

[2] https://www.nag.com/numeric/nl/nagdoc_latest/clhtml/c06/c06conts.html

[3] https://blogs.oracle.com/javamagazine/post/programming-the-gpu-in-java

[4] http://jcuda.org/jcuda/jcufft/JCufft.html

[5]
https://github.com/jcuda/jcuda-samples/tree/master/JCudaSamples/src/main/java/jcuda/jcufft/samples

[6] http://aparapi.github.io/

[7] https://openjdk.java.net/jeps/414


On Tue, 22 Mar 2022 at 10:07, Gilles Sadowski  wrote:

> Hello.
>
> > [...]
> > >
> > > Are we expecting complex-numbers to be an efficient pure java library
> that
> > > could be used by other java libraries such as commons-imaging for data
> > > compression (DCT /JPEG lossy compression)?
> > >
> >
> > Numbers should be seen as a toolbox to be used by other Java
> applications.
> > The best location for routines is something to discuss on the mailing
> list.
> > In the example of DCT, I am not aware if imaging currently has an encoder
> > implementation for this. There is a decoder:
> > org/apache/commons/imaging/formats/jpeg/decoder/Dct.jav
>
> Also:
>
> https://gitbox.apache.org/repos/asf?p=commons-math.git;a=blob;f=commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java
>
> It would be a maintenance boon if "Commons" could come up with
> a consensus about which components must be dependency-free and
> which could depend on other (lower-level) "Commons" components.
>
> [Imaging] is clearly higher-level than [Math] and that such non-obvious
> algorithms should be maintained in a single place.  Through the process
> of modularizing [Math], we have "commons-math-transform" module,
> with zero dependency, so it would bring zero bloat to [Imaging] users if
> we consolidate usage.
>
> Of course, that would imply testing and benchmarking all current
> implementations, and retain the best (taking various axes into account:
> performance, robustness, flexibility).
>
> Regards,
> Gilles
>
> > [...]
>
> -
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>
>


Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-03-22 Thread Gilles Sadowski
Hello.

> [...]
> >
> > Are we expecting complex-numbers to be an efficient pure java library that
> > could be used by other java libraries such as commons-imaging for data
> > compression (DCT /JPEG lossy compression)?
> >
>
> Numbers should be seen as a toolbox to be used by other Java applications.
> The best location for routines is something to discuss on the mailing list.
> In the example of DCT, I am not aware if imaging currently has an encoder
> implementation for this. There is a decoder:
> org/apache/commons/imaging/formats/jpeg/decoder/Dct.jav

Also:
https://gitbox.apache.org/repos/asf?p=commons-math.git;a=blob;f=commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java

It would be a maintenance boon if "Commons" could come up with
a consensus about which components must be dependency-free and
which could depend on other (lower-level) "Commons" components.

[Imaging] is clearly higher-level than [Math] and that such non-obvious
algorithms should be maintained in a single place.  Through the process
of modularizing [Math], we have "commons-math-transform" module,
with zero dependency, so it would bring zero bloat to [Imaging] users if
we consolidate usage.

Of course, that would imply testing and benchmarking all current
implementations, and retain the best (taking various axes into account:
performance, robustness, flexibility).

Regards,
Gilles

> [...]

-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-03-21 Thread Alex Herbert
On Sun, 20 Mar 2022 at 16:49, Sumanth Rajkumar 
wrote:

> Thanks for the feedback Alex!
>
> As suggested, I reviewed the JTransforms and ComplexUtils class in the
> complex streams package.
>
> The existing complex utils class has methods to convert to and from Array
> data structures (the forms used in JTransform) to Complex class.
>
> I can come up with a Java 8/Streams based API for implementing complex
> FFT algorithms of the types in JTransforms and support various methods in
> ComplexUtils
> The streams based complex operations API should allow for decoupling the
> backing data structures.
> This should make it possible to use single API to create an unit test
> suite to benchmark/compare different backing data structures such as single
> arrays, floats or even polar representations
>

Support for the output of Jtransforms ideally should not copy any data.
This would be a wrapper to accept the array in place and allow further
operations on the set of array complex data. At the end the same array can
then be transformed back by JTransforms.

However accepting a stream of Complex objects and performing a collect
operation as a Stream termination operation to different backing data
structures would be something to investigate:

Complex[] c = ...
ComplexList list =
Arrays.stream(c).collect(ComplexCollectors.toList());
double[] data = list.flatten();

Ideally the ComplexCollectors would create a collector to generate data in
a suitable format for any other library, e.g. JTransforms, so that the
flatten operation simply returns the underlying data. Both methods would
require arguments to allow the user to specify the organisation of the
underlying data structure. The flatten method would then have to support
transformation if necessary. The types of structure could be for a 1D
example:

double[] real
double[] imag

// Packed as real = i*2, imag = i*2+1
double[] data

// Packed as real = i, imag = len/2 + i
double[] data

Then support for 2, 3, ND equivalents. In this case the class Gilles
mentioned is useful:
org.apache.commons.numbers.arrays.MultidimensionCounter

Data transformation this way via streams may not be the optimal way to
perform this with regard to memory usage. A transform utility class may be
better suited as it can validate the dimensions of the input size before
any allocation is made for the output data structure. For example you
cannot create a 512*512 2D array if you do not have the correct size input.


>
> As part of the project, I could implement a subset of the FFT operations
> in JTransform using the new streams based Complex Numbers API and
> benchmark it against JTransform implementation
>

This would be repeating a lot of work from JTransforms which already
implements support for parallel processing during the transform. I am not
sure what the gain would be.

Note that a FFT operation must operate on a vector of data, typically a
power of size 2. So that would limit the use in a stream to stripes of
data. Is this your intention? If so how would it differ from a parallel
striped implementation in JTransforms?


>
>
> I understand that we are in the GSOC discussion phase. I am trying to
> understand the background of this project and the requirements in order to
> come up with my GSOC proposal
>
> Can you provide with more information on the envisaged usage of
> Commons-Numbers (especially Complex Numbers), its current usage/users and
> the vision/roadmap for future enhancements
>

I do not have metrics for the usage of numbers. This is something that
requires an analysis of the dependencies of a large number of projects to
create a histogram of the frequency for library usage. I am not aware of a
recent meta analysis where we can obtain such data for Numbers which had
its first release in July 2021.

Typically there is no roadmap for Commons beyond accepting contributions
that add functionality that has general applicability. Future additions to
Numbers could be further refactoring of existing functionality in Commons
Math. There are already many parts of Commons Math that now depend on
Commons Numbers. Since this is a community supported project the direction
is really depicted by the input efforts of the community.


>
> Are we expecting complex-numbers to be an efficient pure java library that
> could be used by other java libraries such as commons-imaging for data
> compression (DCT /JPEG lossy compression)?
>

Numbers should be seen as a toolbox to be used by other Java applications.
The best location for routines is something to discuss on the mailing list.
In the example of DCT, I am not aware if imaging currently has an encoder
implementation for this. There is a decoder:
org/apache/commons/imaging/formats/jpeg/decoder/Dct.jav


>
> Are there other Java/Non-Java (C/Python) libraries that provide similar
> features that I can look into for design inspiration and also benchmark
> Complex Numbers with?
>

Complex numbers are a requirement for a C library that conforms to 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-03-21 Thread Gilles Sadowski
Le lun. 21 mars 2022 à 23:12, Alex Herbert  a écrit :
>
> Hi,
>
> This lost the dev@commons in the to address. I am forwarding to the list to
> include the history.

>From a quick read of the quoted messages below, I believe I must
point out that there is an FFT implementation in Commons Math.[1]
It could be construed as a (high priority) use case.  Thus, it should
be included in benchmarks and possibly adapted to work with the
proposed data-structure(s).

Regards,
Gilles

[1] 
https://gitbox.apache.org/repos/asf?p=commons-math.git;a=blob;f=commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java

>
> On Sun, 20 Mar 2022 at 16:49, Sumanth Rajkumar 
> wrote:
>
> > Thanks for the feedback Alex!
> >
> > As suggested, I reviewed the JTransforms and ComplexUtils class in the
> > complex streams package.
> >
> > The existing complex utils class has methods to convert to and from Array
> > data structures (the forms used in JTransform) to Complex class.
> >
> > I can come up with a Java 8/Streams based API for implementing complex
> > FFT algorithms of the types in JTransforms and support various methods in
> > ComplexUtils
> > The streams based complex operations API should allow for decoupling the
> > backing data structures.
> > This should make it possible to use single API to create an unit test
> > suite to benchmark/compare different backing data structures such as single
> > arrays, floats or even polar representations
> >
> > As part of the project, I could implement a subset of the FFT operations
> > in JTransform using the new streams based Complex Numbers API and
> > benchmark it against JTransform implementation
> >
> >
> > I understand that we are in the GSOC discussion phase. I am trying to
> > understand the background of this project and the requirements in order to
> > come up with my GSOC proposal
> >
> > Can you provide with more information on the envisaged usage of
> > Commons-Numbers (especially Complex Numbers), its current usage/users and
> > the vision/roadmap for future enhancements
> >
> > Are we expecting complex-numbers to be an efficient pure java library that
> > could be used by other java libraries such as commons-imaging for data
> > compression (DCT /JPEG lossy compression)?
> >
> > Are there other Java/Non-Java (C/Python) libraries that provide similar
> > features that I can look into for design inspiration and also benchmark
> > Complex Numbers with?
> >
> > Thanks
> > Sumanth
> >
> >
> > On Tue, 15 Mar 2022 at 20:50, Alex Herbert 
> > wrote:
> >
> >> Hi Sumanth,
> >>
> >> These changes to use static methods with functional interfaces is an
> >> improvement. However I would advise that we consider the use cases for this
> >> functionality to ensure that any design does not prevent extension and also
> >> allows full flexibility to achieve various tasks.
> >>
> >> For example:
> >>
> >> - multiply all the complex numbers in one list with another
> >> - wrap an existing complex number data structure, for example the FFT
> >> result produced by JTransforms [1]
> >>
> >> This project originates from a previous enhancement request that was made
> >> to store a large set of complex numbers efficiently. The argument was that
> >> the 16 bytes to store 2 doubles is inflated by the object allocation to
> >> store a Complex, perhaps by even double the 16 bytes. The natural storage
> >> would be two arrays of doubles, but what about 1 linear array packed as
> >> real/imag for each number. This will be able to store half as many numbers
> >> but access to each will take advantage of efficient caching when
> >> reading/writing memory. The JTransforms library (and others) may have ideas
> >> for useful data structures.
> >>
> >> Unfortunately I cannot find if there was a Jira ticket for this or it is
> >> only in the mailing archives. I've added links to the GSoC ticket for the
> >> other tickets that mention complex number array utils and streams. However
> >> these do not have a use case. Perhaps an investigation of the functionality
> >> in the unreleased commons-number-complex-streams package would be the place
> >> to start. The original author of that package is not actively involved in
> >> the development any more.
> >>
> >> I should also point out the process for GSoC. It is outlined here [2]. In
> >> short the initial period is about understanding what a project may involve.
> >> Then you create a proposal for the project that is ranked with all the
> >> other potential coders. Some projects are selected. It is only then that
> >> the formal coding process begins and you have 12 weeks to create some code.
> >> Previous years have had a timeline but this year the only date on the info
> >> page is April 4 - 19 for when applications open. So right now we are in the
> >> discussion phase. Any code developed now technically cannot be part of
> >> GSoC, although this is not strictly enforced.
> >>
> >> Regards,
> >>
> >> Alex
> >>
> >> [1] 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-03-21 Thread Alex Herbert
Hi,

This lost the dev@commons in the to address. I am forwarding to the list to
include the history.

On Sun, 20 Mar 2022 at 16:49, Sumanth Rajkumar 
wrote:

> Thanks for the feedback Alex!
>
> As suggested, I reviewed the JTransforms and ComplexUtils class in the
> complex streams package.
>
> The existing complex utils class has methods to convert to and from Array
> data structures (the forms used in JTransform) to Complex class.
>
> I can come up with a Java 8/Streams based API for implementing complex
> FFT algorithms of the types in JTransforms and support various methods in
> ComplexUtils
> The streams based complex operations API should allow for decoupling the
> backing data structures.
> This should make it possible to use single API to create an unit test
> suite to benchmark/compare different backing data structures such as single
> arrays, floats or even polar representations
>
> As part of the project, I could implement a subset of the FFT operations
> in JTransform using the new streams based Complex Numbers API and
> benchmark it against JTransform implementation
>
>
> I understand that we are in the GSOC discussion phase. I am trying to
> understand the background of this project and the requirements in order to
> come up with my GSOC proposal
>
> Can you provide with more information on the envisaged usage of
> Commons-Numbers (especially Complex Numbers), its current usage/users and
> the vision/roadmap for future enhancements
>
> Are we expecting complex-numbers to be an efficient pure java library that
> could be used by other java libraries such as commons-imaging for data
> compression (DCT /JPEG lossy compression)?
>
> Are there other Java/Non-Java (C/Python) libraries that provide similar
> features that I can look into for design inspiration and also benchmark
> Complex Numbers with?
>
> Thanks
> Sumanth
>
>
> On Tue, 15 Mar 2022 at 20:50, Alex Herbert 
> wrote:
>
>> Hi Sumanth,
>>
>> These changes to use static methods with functional interfaces is an
>> improvement. However I would advise that we consider the use cases for this
>> functionality to ensure that any design does not prevent extension and also
>> allows full flexibility to achieve various tasks.
>>
>> For example:
>>
>> - multiply all the complex numbers in one list with another
>> - wrap an existing complex number data structure, for example the FFT
>> result produced by JTransforms [1]
>>
>> This project originates from a previous enhancement request that was made
>> to store a large set of complex numbers efficiently. The argument was that
>> the 16 bytes to store 2 doubles is inflated by the object allocation to
>> store a Complex, perhaps by even double the 16 bytes. The natural storage
>> would be two arrays of doubles, but what about 1 linear array packed as
>> real/imag for each number. This will be able to store half as many numbers
>> but access to each will take advantage of efficient caching when
>> reading/writing memory. The JTransforms library (and others) may have ideas
>> for useful data structures.
>>
>> Unfortunately I cannot find if there was a Jira ticket for this or it is
>> only in the mailing archives. I've added links to the GSoC ticket for the
>> other tickets that mention complex number array utils and streams. However
>> these do not have a use case. Perhaps an investigation of the functionality
>> in the unreleased commons-number-complex-streams package would be the place
>> to start. The original author of that package is not actively involved in
>> the development any more.
>>
>> I should also point out the process for GSoC. It is outlined here [2]. In
>> short the initial period is about understanding what a project may involve.
>> Then you create a proposal for the project that is ranked with all the
>> other potential coders. Some projects are selected. It is only then that
>> the formal coding process begins and you have 12 weeks to create some code.
>> Previous years have had a timeline but this year the only date on the info
>> page is April 4 - 19 for when applications open. So right now we are in the
>> discussion phase. Any code developed now technically cannot be part of
>> GSoC, although this is not strictly enforced.
>>
>> Regards,
>>
>> Alex
>>
>> [1] https://github.com/wendykierp/JTransforms
>> [2] https://summerofcode.withgoogle.com/how-it-works
>>
>>
>> On Tue, 15 Mar 2022 at 02:23, Sumanth Rajkumar <
>> rajkumar.suma...@gmail.com> wrote:
>>
>>> Hi Alex/Gilles
>>>
>>> Thank you both for the detailed review. I think I have a better
>>> understanding now.
>>>
>>> 1) Refactor using Functional Interfaces and move current instance
>>> methods to static methods
>>>
>>>  As suggested, I have attempted to refactor the Complex class to extract
>>> the functions out to static methods and use Functional interfaces
>>>
>>> I have added following Complex Functional interfaces similar to
>>> Functions and Operators defined in java.util.function but only using
>>> primitive doubles 

Re: [numbers][gsoc] GSoC 2022 - NUMBERS-186 Proposal

2022-03-13 Thread Alex Herbert
Hi,

Thanks for your interest in Commons Numbers.

On Mon, 14 Mar 2022 at 00:09, Gilles Sadowski  wrote:

> >
> > My partial implementation (with TODOs for many operations) is available
> > here.
> >
> https://github.com/sumanth-rajkumar/commons-numbers/blob/sumanth-gsoc-22/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex/ComplexList.java


Thanks for the implementation idea. This is a literal implementation of a
List. I think we should take a step back and find use cases for a
large set of complex numbers. That should drive the API design.

For example a common operation with complex numbers is to conjugate
multiply the fast fourier transform of two data arrays. The conjugate
multiply in the frequency domain is equivalent to the correlation in the
spatial domain. So I would require:

ComplexList a;
ComplexList b;

a.conj().multiply(b);

But what is the most appropriate method to do this? I do not think we want
to implement full matrix functionality for multiplication of arrays. But we
should allow an API that makes this type of work efficient in terms of
memory usage, i.e. zero object allocation during computation (avoid
creating Complex instances) and ideally no intermediate array allocation.
So in the above I do not want to create an entire list of conjugates before
multiplying by another complex number. I also want the option to write to a
new array or back to the original one.

So should we have some type of generic interface for an operation on a
Complex:

interface ComplexFunction {
   interface ComplexResult {
  void complex(double real, double imag);
   }
   void apply(double re, double im, ComplexResult);
}

Then a list to allow operations on elements in place. For example to
compute the conjugate:

ComplexList a;
a.forEach((re, im, result) -> result.complex(re, -im));

All operations in the Complex class can be rewritten as static methods
using a minimal set of functional interfaces.

static void conj(double re, double im, ComplexResult result) {
result.complex(re, -im);
}

The operation then becomes:

ComplexList a;
a.forEach(Complex::conj);

Which is a bit less cumbersome to write.

Operations could be chained using a 'andThen' method in the interface:

ComplexList a;
a.forEach(((ComplexFunction) Complex::conj).andThen(Complex::sin));

I've not considered exactly how this will work in practice.

Functions that convert to a real number (such as abs()) could write 0 to
the imaginary.

The specifics will depend on all the operations in Complex. So a start
point may be to refactor the class to expose all the instance methods as
static methods that take input and write the result to a destination. These
can be used by (all) the Complex instance methods. I say (all) as some may
be more efficient to leave as is, namely the simple methods like negate or
conjugate, and the operations with real numbers.

Re: Your code implementation

I notice that the implementation for the expandable array backed list and
hash code generation are "heavily reliant" on the JDK (11?) source for
ArrayList and Arrays. It is good practice to be aware of the license terms
of any open source code project you may wish to use. The Oracle Open
JDK license terms are here [1]. This is under the GNU GPL v2 license which
is not permissible to be used in an ASF project [2]. In general it is fine
to look at the JDK source code to see how the function works or find bugs.
However any new code reimplementing the functionality should be done as if
blind to the code and only using a contractual specification of what the
code is meant to do. The modern javadoc effort by the JDK tries to provide
a very good specification of each method contract. So it is often possible
to write the same function from the javadoc description. An ideal javadoc
should have this as its goal. Effectively this would be someone telling you
what the code does but not showing you how:

1. A default array size of 10
2. Backing array will grow using a factor of 50% up to the maximum array
size
3. Overflow of the maximum array size will result in OutOfMemoryError
4. Index operations outside of the current list size [0, size) will throw
ArrayIndexOutOfBoundException
5. etc

Alex

[1] http://openjdk.java.net/legal/gplv2+ce.html
[2] https://www.apache.org/legal/resolved.html#category-x