Le lun. 21 mars 2022 à 23:12, Alex Herbert <alex.d.herb...@gmail.com> 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 <rajkumar.suma...@gmail.com> > 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 <alex.d.herb...@gmail.com> > > 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 and avoiding any Object creation overheads > >>> > >>> @FunctionalInterface > >>> public interface ComplexFunction { > >>> <R> R apply(double r, double i, ComplexResult<R> result); > >>> } > >>> > >>> @FunctionalInterface > >>> public interface ComplexBiFunction { > >>> <R> R apply(double r1, double i1, double r2, double i2, > >>> ComplexResult<R> result); > >>> } > >>> > >>> > >>> @FunctionalInterface > >>> public interface ComplexResult<R> { > >>> R apply(double r, double i); > >>> default <V> ComplexResult<V> andThen(Function<? super R, ? extends > >>> V> after) { > >>> Objects.requireNonNull(after); > >>> return (r, i) -> after.apply(apply(r, i)); > >>> } > >>> default ComplexResult<R> compose(ComplexFunction before) { > >>> Objects.requireNonNull(before); > >>> return (r, i) -> before.apply(r, i, (x, y) -> apply(x, y)); > >>> } > >>> } > >>> > >>> > >>> > >>> I have refactored a few Functions (exp, conj, asin) and a few > >>> BFunctions (multiply, divide) as static functions into a new > >>> ComplexFunctions class > >>> > >>> I have modified the existing implementations for above in the Complex > >>> class to use the new static functions using the new Function interfaces > >>> > >>> I have also refactored ComplexList to apply the above function > >>> interfaces in forEach methods as suggested. These apply the results in > >>> place without incurring object overheads > >>> > >>> Refactored source is available here for review > >>> > >>> https://github.com/sumanth-rajkumar/commons-numbers/tree/sumanth-gsoc-22/commons-numbers-complex/src/main/java/org/apache/commons/numbers/complex > >>> > >>> Please let me know if the above changes are on expected lines? > >>> > >>> 2) List Implementation > >>> > >>> Thanks for the feedback on the license issue. I should be able > >>> refactor this as suggested just using the javadoc specifications > >>> > >>> > >>> -Sumanth. > >>> > >>> > >>> On Sun, 13 Mar 2022 at 21:39, Alex Herbert <alex.d.herb...@gmail.com> > >>> wrote: > >>> > >>>> Hi, > >>>> > >>>> Thanks for your interest in Commons Numbers. > >>>> > >>>> On Mon, 14 Mar 2022 at 00:09, Gilles Sadowski <gillese...@gmail.com> > >>>> 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<Complex>. 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 > >>>> > >>> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org