Re: [Numbers] Arrays of "Complex" objects and RAM

2019-11-07 Thread Eric Barnhill
On Thu, Nov 7, 2019 at 3:25 PM Gilles Sadowski  wrote:

> Le jeu. 7 nov. 2019 à 18:36, Eric Barnhill  a
> écrit :
> >
> > I should also add on this note, my use case for developing ComplexUtils
> in
> > the first place was compatibility with JTransforms and JOCL. In both
> cases
> > I wanted to convert Complex[] arrays into interleaved double[] arrays to
> > feed into algorithms using those libraries.
>
> Implicit in my remark below is the question: Where does the "Complex[]"
> come from?  If it is never a good idea to create such an array, why provide
> code to convert from it?  Do we agree that we should rather create the
> "ComplexList" abstraction, including accessors that shape the data for
> use with e.g. JTransforms?
>
>
I completely agree this is a superior solution and look forward to its
development.


Re: [Numbers] Arrays of "Complex" objects and RAM

2019-11-07 Thread Gilles Sadowski
Le jeu. 7 nov. 2019 à 18:36, Eric Barnhill  a écrit :
>
> I should also add on this note, my use case for developing ComplexUtils in
> the first place was compatibility with JTransforms and JOCL. In both cases
> I wanted to convert Complex[] arrays into interleaved double[] arrays to
> feed into algorithms using those libraries.

Implicit in my remark below is the question: Where does the "Complex[]"
come from?  If it is never a good idea to create such an array, why provide
code to convert from it?  Do we agree that we should rather create the
"ComplexList" abstraction, including accessors that shape the data for
use with e.g. JTransforms?

Regards,
Gilles

> On Thu, Nov 7, 2019 at 9:34 AM Eric Barnhill  wrote:
>
> >
> >
> > On Thu, Nov 7, 2019 at 6:09 AM Gilles Sadowski 
> > wrote:
> >
> >>
> >> This is also what started this thread: The user called the Commons Math's
> >> FFT utilities using arrays of "Complex" objects and got the "OutOfMemory"
> >> error.  Hence the question of whether storing many "Complex" objects is
> >> ever useful, as compared to the "ComplexList", backed with an array of
> >> primitives, and instantiating transient "Complex" instances on-demand.
> >>
> >
> > I'm glad it has provoked such improvements. As you implicitly reference in
> > your reply, probably we should just be shading JTransforms in the first
> > place. I started using JTransforms because I had trouble using the
> > commons-math FFT as well.
> >

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



Re: [numbers] Bug in complex multiply + divide + isNaN

2019-11-07 Thread Alex Herbert



> On 7 Nov 2019, at 17:31, Eric Barnhill  wrote:
> 
> […]
> 
> Well that's interesting, I did not see that the standard specified
> all-vs-all methods in all those cases. There isn't a performance gain for
> multiplying by an imaginary double like there is for a real double,

Not for imaginary against real, but the matrix states there is for imaginary 
against complex:

Multiplying by a real double:

u * (x + iy) = (xu) + i (yu)

Multiplying by an imaginary (no real):

iv * (x + iy) = (-yv) + i (xv)

So the performance gain is the same. One use case is in the previously 
mentioned trigonomic identities where you wish to multiply by I or -I. In this 
case v is 1 or -1 and so the specialisation is:

i * (x + iy) = -y + ix
-i * (x + iy) = y + i-x

I’ve used this specialisation internally but I wonder if it would be useful in 
the API.

Alex


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



Re: [numbers] Bug in complex multiply + divide + isNaN

2019-11-07 Thread Alex Herbert


> On 7 Nov 2019, at 17:31, Eric Barnhill  wrote:
> 
> On Thu, Nov 7, 2019 at 3:59 AM Alex Herbert 
> wrote:
> 
>> 
>> There is a matrix for real/imaginary/complex all-vs-all additive and
>> multiplicative operators in the standard (tables in G.5.1 and G.5.2).
>> The question is do we want to support the entire matrix:
>> 
>> Covered:
>> 
>> Complex.multiplyReal(double x) as  Complex.multiply(double x)
>> Complex.divideReal(double x)   as  Complex.divide(double x)
>> Complex.addReal(double x)  as  Complex.add(double x)
>> Complex.subtractReal(double x) as  Complex.subtract(double x)
>> 
>> Not covered:
>> 
>> Complex.multiplyImaginary(double x)
>> Complex.divideImaginary(double x)
>> Complex.addImaginary(double x)
>> Complex.subtractImaginary(double x)
>> Complex.subtractFromReal(double x)
>> Complex.subtractFromImaginary(double x)
>> 
>> 
>> I am going through Complex now to fix code coverage and make it in line
>> with the C.99 standard. I will push all the config changes with the
>> update to Complex. Should be done be end of today.
> 
> 
> 
> Well that's interesting, I did not see that the standard specified
> all-vs-all methods in all those cases. There isn't a performance gain for
> multiplying by an imaginary double like there is for a real double, as one
> has to deal with imaginary*imaginary, so one might as well just pass a
> Complex rather than an imaginary double. Consequently I would imagine
> implementations of that corner of the standard's matrix are pretty rare.
> But I see no reason not to have it for completeness and continuing the goal
> I set, of being the only non-C library that I've ever seen that fulfills
> the whole standard.
> 
> +1

My changes to the tests for Complex have taken longer than I expected. I will 
continue tomorrow and will push something by the end of tomorrow.

One thing I noted is that although there is coverage of edge cases there is not 
a lot of coverage of the methods using ‘ordinary’ data. Some of the coverage 
comes from methods being used in other methods and not tested directly. I’ll 
fix up the code coverage and then will make an attempt to generate some results 
of complex operations using the GNU C compiler that can be incorporated into 
tests of the individual methods. This will be along the lines of:

void assertOperation(Complex z, UnaryOperator op, Complex expected) {
   // Check: expected == op.apply(z)
}

for all the operations on complex data.

I also note that the C.99 standard uses the following definitions of some 
functions using others:

casin(z) = -i casinh(iz)
catan(z) = -i catanh(iz)
ccos(z) = ccosh(iz)
csin(z) = -i csinh(iz)
ctan(z) = -i ctanh(iz)


The code currently was not doing this. It implemented the functions on the left 
directly. This means that all the edge cases in the function on the right (as 
these are tested in the CStandardTest) were missed from the function on the 
left. So for now I have implemented the equalities as defined above and 
commented out the original code.

Multiplication by I and -I is a straightforward real <=> imaginary swap with an 
appropriate sign update. So using the equalities is simple and more 
maintainable as some methods duplicate a lot of the same computation.

Alex








Re: [VOTE] Release Apache Commons RNG 1.3 based on RC1

2019-11-07 Thread Pascal Schumacher

+1

Am 05.11.2019 um 17:36 schrieb Alex Herbert:

We have fixed quite a few bugs and added some significant enhancements
since Apache Commons RNG 1.2 was released, so I would like to release
Apache Commons RNG 1.3.

Apache Commons RNG 1.3 RC1 is available for review here:
  https://dist.apache.org/repos/dist/dev/commons/rng/1.3-RC1/
  https://home.apache.org/~aherbert/commons-rng-1.3-RC1-site/

Tag name:
  RNG_1_3_RC1 (signature can be checked from git using 'git tag -v
RNG_1_3_RC1')

Tag URL:
https://gitbox.apache.org/repos/asf?p=commons-rng.git;a=commit;h=43f290e68c31e5bea6cde97c7e999c2e1f2562b2


Commit ID the tag points at:
  43f290e68c31e5bea6cde97c7e999c2e1f2562b2

Maven artifacts are here:
https://repository.apache.org/content/repositories/orgapachecommons-1476/org/apache/commons/


These are the artifacts and their SHA 512 hashes:
310c0582b80c60fb159846f9615c7952b3c405265955392d77b16d7cfac9e8c5f2c680686e526b412ab8b4356ef9ecd07977764c31db8e02bef40e37b47ac27a
commons-rng-1.0-bin.tar.gz
e0247ea82aff57cc86ac904ae482c193b7edd5253d26f87fc590b50a738d5fa5c4a6b3b24cd6a48c459e18156ade2588d8c9d12c9a04d15570780240d29ef406
commons-rng-1.0-bin.zip
f33b922a9d8bc6098bd0e9a98859b17e1cdda21922f136b568868b21af274fdf3d78456a5c73c26c665205a22493836d59b1d33822c4a5c58e82ba64eadcb5e1
commons-rng-1.0-src.tar.gz
ef4fe63ebbd76e8d95b5f054fed76a40a85f5dd99ca2406a31fb95b593ed3d96b29389bf82424e18895192751689d7590404c8b1d90b28878271c79cad3be18b
commons-rng-1.0-src.zip

The source code contains examples that are not part of the public API.
These examples contain Java 9 modules and are enabled using a profile
(see below).

An error when building the Java 9 modules site/javadoc under JDK 11 is
a known issue as the javadoc command errors when documenting Java 9
modules that include code from the unamed module.

Note: Testing randomness using statistical thresholds results in
failures at a given probability. The 'maven-surefire-plugin' is
configured to re-run tests that fail, and pass the build if they
succeed within the allotted number of reruns (the test will be marked
as 'flaky' in the report).

I have tested this with:

'mvn clean install site' using:

***
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3;
2018-10-24T19:41:47+01:00)
Maven home: /usr/local/apache-maven-3.6.0
Java version: 1.8.0_222, vendor: Private Build, runtime:
/usr/lib/jvm/java-8-openjdk-amd64/jre
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.4.0-166-generic", arch: "amd64", family:
"unix"
***

***
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3;
2018-10-24T19:41:47+01:00)
Maven home: /usr/local/apache-maven-3.6.0
Java version: 11.0.5, vendor: AdoptOpenJDK, runtime:
/usr/lib/jvm/jdk-11.0.5+10
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.4.0-166-generic", arch: "amd64", family:
"unix"
***

Java 9 modules in the examples modules.

'mvn -Pcommons-rng-examples clean install site' using:

***
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3;
2018-10-24T19:41:47+01:00)
Maven home: /usr/local/apache-maven-3.6.0
Java version: 9, vendor: Oracle Corporation, runtime: /usr/lib/jvm/jdk-9
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.4.0-166-generic", arch: "amd64", family:
"unix"
***

'mvn -Pcommons-rng-examples clean install' using:

***
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3;
2018-10-24T19:41:47+01:00)
Maven home: /usr/local/apache-maven-3.6.0
Java version: 11.0.5, vendor: AdoptOpenJDK, runtime:
/usr/lib/jvm/jdk-11.0.5+10
Default locale: en_GB, platform encoding: UTF-8
OS name: "linux", version: "4.4.0-166-generic", arch: "amd64", family:
"unix"
***

Details of changes since 1.2 are in the release notes:
https://dist.apache.org/repos/dist/dev/commons/rng/1.3-RC1/RELEASE-NOTES.txt

https://home.apache.org/~aherbert/commons-rng-1.3-RC1-site/changes-report.html


Site:
https://home.apache.org/~aherbert/commons-rng-1.3-RC1-site/index.html
    (note some *relative* links are broken and the 1.3 directories are
not yet created - these will be OK once the site is deployed.)

CLIRR Report (compared to 1.2):
https://home.apache.org/~aherbert/commons-rng-1.3-RC1-site/commons-rng-client-api/clirr-report.html

https://home.apache.org/~aherbert/commons-rng-1.3-RC1-site/commons-rng-core/clirr-report.html

https://home.apache.org/~aherbert/commons-rng-1.3-RC1-site/commons-rng-simple/clirr-report.html

https://home.apache.org/~aherbert/commons-rng-1.3-RC1-site/commons-rng-sampling/clirr-report.html


RAT Report:
https://home.apache.org/~aherbert/commons-rng-1.3-RC1-site/rat-report.html


KEYS:
  https://www.apache.org/dist/commons/KEYS

Please review the release candidate and vote.
This vote will close no sooner that 72 hours from now.

  [ ] +1 Release these artifacts
  [ ] +0 OK, but...
  [ ] -0 OK, but really should fix...
  [ ] -1 I oppose this release because...

Thank you,

Alex Herbert,
Release Manager (using key 

Re: [Numbers] Arrays of "Complex" objects and RAM

2019-11-07 Thread Eric Barnhill
I should also add on this note, my use case for developing ComplexUtils in
the first place was compatibility with JTransforms and JOCL. In both cases
I wanted to convert Complex[] arrays into interleaved double[] arrays to
feed into algorithms using those libraries.

On Thu, Nov 7, 2019 at 9:34 AM Eric Barnhill  wrote:

>
>
> On Thu, Nov 7, 2019 at 6:09 AM Gilles Sadowski 
> wrote:
>
>>
>> This is also what started this thread: The user called the Commons Math's
>> FFT utilities using arrays of "Complex" objects and got the "OutOfMemory"
>> error.  Hence the question of whether storing many "Complex" objects is
>> ever useful, as compared to the "ComplexList", backed with an array of
>> primitives, and instantiating transient "Complex" instances on-demand.
>>
>
> I'm glad it has provoked such improvements. As you implicitly reference in
> your reply, probably we should just be shading JTransforms in the first
> place. I started using JTransforms because I had trouble using the
> commons-math FFT as well.
>


Re: [Numbers] Arrays of "Complex" objects and RAM

2019-11-07 Thread Eric Barnhill
On Thu, Nov 7, 2019 at 6:09 AM Gilles Sadowski  wrote:

>
> This is also what started this thread: The user called the Commons Math's
> FFT utilities using arrays of "Complex" objects and got the "OutOfMemory"
> error.  Hence the question of whether storing many "Complex" objects is
> ever useful, as compared to the "ComplexList", backed with an array of
> primitives, and instantiating transient "Complex" instances on-demand.
>

I'm glad it has provoked such improvements. As you implicitly reference in
your reply, probably we should just be shading JTransforms in the first
place. I started using JTransforms because I had trouble using the
commons-math FFT as well.


Re: [numbers] Bug in complex multiply + divide + isNaN

2019-11-07 Thread Eric Barnhill
On Thu, Nov 7, 2019 at 3:59 AM Alex Herbert 
wrote:

>
> There is a matrix for real/imaginary/complex all-vs-all additive and
> multiplicative operators in the standard (tables in G.5.1 and G.5.2).
> The question is do we want to support the entire matrix:
>
> Covered:
>
> Complex.multiplyReal(double x) as  Complex.multiply(double x)
> Complex.divideReal(double x)   as  Complex.divide(double x)
> Complex.addReal(double x)  as  Complex.add(double x)
> Complex.subtractReal(double x) as  Complex.subtract(double x)
>
> Not covered:
>
> Complex.multiplyImaginary(double x)
> Complex.divideImaginary(double x)
> Complex.addImaginary(double x)
> Complex.subtractImaginary(double x)
> Complex.subtractFromReal(double x)
> Complex.subtractFromImaginary(double x)
>
>
> I am going through Complex now to fix code coverage and make it in line
> with the C.99 standard. I will push all the config changes with the
> update to Complex. Should be done be end of today.



Well that's interesting, I did not see that the standard specified
all-vs-all methods in all those cases. There isn't a performance gain for
multiplying by an imaginary double like there is for a real double, as one
has to deal with imaginary*imaginary, so one might as well just pass a
Complex rather than an imaginary double. Consequently I would imagine
implementations of that corner of the standard's matrix are pretty rare.
But I see no reason not to have it for completeness and continuing the goal
I set, of being the only non-C library that I've ever seen that fulfills
the whole standard.

+1


Re: [Numbers] Arrays of "Complex" objects and RAM

2019-11-07 Thread Gilles Sadowski
>  [...]
> >>>
> >>> public class ComplexArray {
> >>> private final MultidimensionalCounter counter;
> >>> // ...
> >>>
> >>> public ComplexArray(int... dimensions) {
> >>> counter = new MultidimensionalCounter(dimensions);
> >>> data = new data[counter.getSize()];
> >>> }
> >>>
> >>> /**
> >>>  * @param indices Storage location.
> >>>  * @return the complex number stored at the given location.
> >>>  */
> >>> public Complex get(int... indices) {
> >>> return data[counter.getCount(indices)];
> >>> }
> >>> }
> >>>
> >>> Or perhaps the data cube should be an additional abstraction on top of
> >>> "ComplexArray" (?).
> >> I think adding the abstraction on top is easier.
> >>
> >> Array can be renamed to Collection/List? Thus the count is the only
> >> thing that matters, and optionally a constant time access get(int index)
> >> method.
> >
> > +1
> >
> >>
> >> This can later be reshaped to a Matrix representation using the
> >> MultidimensionalCounter pattern.
> >>
> >> We have two use cases:
> >>
> >> 1. You know the final count of Complex objects
> >> 2. You do not know the count of Complex objects
> >>
> >> Use case 2 is used in streams where the ComplexList must be expandable
> >> for use as a collector. This can be satisfied with a constructor with an
> >> initial capacity. The ComplexList would thus offer a specialisation of
> >> ArrayList by storing the Complex objects using primitive array(s).
> >>
> >> Use case 2 rules out the possibility of immutability. This is the type
> >> of functionality under discussion and could be served using an interface
> >> to allow different implementations:
> >>
> >> public interface ComplexList {
> >> [...]
> >> }
> >
> > +1
> >
> >> This could be separated to put the set and add methods in a
> >> sub-interface allowing the top level interface to be an immutable object.
> >
> > Perhaps better to follow the JDK convention and provide a
> >public static ComplexList unmodifiableList(ComplexList delegate)
> > method.
> >
> >> However the apply functions currently are specified using Complex.
> >> Efficiency would be gained using primitive specialisations for operating
> >> on 1 or 2 complex numbers and outputting the results to a provided 
> >> consumer:
> >>
> >> public interface ComplexProvider {
> >> /**
> >>  * Gets the real component of the complex number.
> >>  *
> >>  * @return the real component
> >>  */
> >> double getReal();
> >>
> >> /**
> >>  * Gets the imaginary component of the complex number.
> >>  *
> >>  * @return the imaginary component
> >>  */
> >> double getImaginary();
> >> }
> >>
> >> public interfaceComplexProvider {
> >> /**
> >>  * Accept the components of the complex number.
> >>  * Optionally return a new ComplexProvider with the components.
> >>  *
> >>  * @param real the real
> >>  * @param imaginary the imaginary
> >>  * @return the complex provider (or null)
> >>  */
> >> ComplexProvider accept(double real, double imaginary);
> >> }
> >
> > What is gained wrt using "Complex" instances directly?
>
> The above is a typo. The accept method should be in a ComplexConsumer 
> interface.
>
> If the data is in a primitive array you would like to be able to access it, 
> and then set it back to the same array or a different array without going 
> through creation of a Complex for each (real, imaginary) pair. So the 
> ComplexProvider and ComplexConsumer provide an input and output for any 
> function that changes the complex data. I’ve made it a bit more complicated 
> with the ComplexConsumer returning a ComplexProvider just to allow all the 
> methods in Complex to be rewritten to provide static methods that can use 
> these interfaces.

I can see that one pass through the primitive array could yield the "real"
and "imaginary" arguments to "accept"; but it must return an instance of
a class (that implements "ComplexProvider"); hence calling a constructor.
In a chain of operations, only the first call to the constructor is avoided.

>
> A simpler approach is for the ComplexList to allow modification in-place by 
> providing a list cursor that can traverse the list (like an iterator) and 
> also skip to positions. It would allow get and set of the data at the current 
> position. This cursor could be used by another class to apply functions in 
> place to the data. The functions could be a user specified generic function 
> using the ComplexFunction interface I suggested.

Still, I don't see what is the gain wrt to creating a result "ComplexList" and
let the caller decide whether to replace the input data with the result:
ComplexList in = ...
ComplexList out = in.apply(function);
in = out;

> I think that performance would have to be assessed for various prototypes. 
> Some of the 

Re: [numbers] Bug in complex multiply + divide + isNaN

2019-11-07 Thread Gilles Sadowski
Le jeu. 7 nov. 2019 à 12:59, Alex Herbert  a écrit :
>
>
> On 07/11/2019 11:45, Gilles Sadowski wrote:
> > Hello.
> >
> >>> [...]
> >>>
>  Also looking at Complex it would benefit from:
> 
>  public Complex subtractFrom(double minuend) {
>  return new Complex(minuend - real, imaginary);
>  }
> >>> Is it part of the "standard"?
> >>> IMHO, it's fairly confusing, as nothing in the name indicates
> >>> that the operation only applies to the real part.
> >> The same applies for the add(real) and subtract(real) methods.
> >>
> >> What is confusing is the unconventional reverse ordering of 
> >> z.subtractFrom(a) == a - z. I’m not happy about it but the javadoc can 
> >> explain the outcome.
> > Actually, what confuses me is that the above equality does not hold:
> >double a = 5;
> >Complex z = Complex.of(1, 3);
> >Complex z2 = z.subtractFrom(a);
> > would yield
> >4 + 3 i
> > whereas
> >Complex z2 = Complex.of(a).subtract(z);
> > would yield
> >4 - 3 i
>
> You are right, I had my use of Complex incorrect. Sorry.
>
> The imaginary part should also be subtracted from zero thus the code
> should be an equivalent with an imaginary of 0:
>
> public Complex subtractFrom(double minuend) {
> return new Complex(minuend - real, 0 - imaginary);
> }
>
> Equivalent to (as you state):
>
> double a = ...;
>
> Complex z = ...;
>
> Complex y = Complex.ofReal(a).subtract(z);

So this would spare one instantiation.
Not sure it would gain much in absolute time for most uses, but there
is no arguing that it is a gain.  [Although, if nit-picking, one could imagine
that the JIT optimization will kick in later if subtraction usage is spread
among the two methods, and thus could be a loss in absolute time for
some uses...]

> There is a matrix for real/imaginary/complex all-vs-all additive and
> multiplicative operators in the standard (tables in G.5.1 and G.5.2).
> The question is do we want to support the entire matrix:

This a more straightforward possible requirement.

> Covered:
>
> Complex.multiplyReal(double x) as  Complex.multiply(double x)
> Complex.divideReal(double x)   as  Complex.divide(double x)
> Complex.addReal(double x)  as  Complex.add(double x)
> Complex.subtractReal(double x) as  Complex.subtract(double x)
>
> Not covered:
>
> Complex.multiplyImaginary(double x)
> Complex.divideImaginary(double x)
> Complex.addImaginary(double x)
> Complex.subtractImaginary(double x)
> Complex.subtractFromReal(double x)
> Complex.subtractFromImaginary(double x)

I'm fine with adding these methods for consistency and completeness.
It may have the advantage to make it slightly easier to port algorithms
written in C++ if all the methods have their exact counterpart in Java.

Regards,
Gilles

>
>
> I am going through Complex now to fix code coverage and make it in line
> with the C.99 standard. I will push all the config changes with the
> update to Complex. Should be done be end of today.
>
> Then we can look at fixing checkstyle and PMD.
>
>
>>> [...]

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



Re: [numbers] Bug in complex multiply + divide + isNaN

2019-11-07 Thread Alex Herbert


On 07/11/2019 11:45, Gilles Sadowski wrote:

Hello.


[...]


Also looking at Complex it would benefit from:

public Complex subtractFrom(double minuend) {
return new Complex(minuend - real, imaginary);
}

Is it part of the "standard"?
IMHO, it's fairly confusing, as nothing in the name indicates
that the operation only applies to the real part.

The same applies for the add(real) and subtract(real) methods.

What is confusing is the unconventional reverse ordering of z.subtractFrom(a) 
== a - z. I’m not happy about it but the javadoc can explain the outcome.

Actually, what confuses me is that the above equality does not hold:
   double a = 5;
   Complex z = Complex.of(1, 3);
   Complex z2 = z.subtractFrom(a);
would yield
   4 + 3 i
whereas
   Complex z2 = Complex.of(a).subtract(z);
would yield
   4 - 3 i


You are right, I had my use of Complex incorrect. Sorry.

The imaginary part should also be subtracted from zero thus the code 
should be an equivalent with an imaginary of 0:


   public Complex subtractFrom(double minuend) {
   return new Complex(minuend - real, 0 - imaginary);
   }

Equivalent to (as you state):

double a = ...;

Complex z = ...;

Complex y = Complex.ofReal(a).subtract(z);

There is a matrix for real/imaginary/complex all-vs-all additive and 
multiplicative operators in the standard (tables in G.5.1 and G.5.2). 
The question is do we want to support the entire matrix:


Covered:

Complex.multiplyReal(double x) as  Complex.multiply(double x)
Complex.divideReal(double x)   as  Complex.divide(double x)
Complex.addReal(double x)  as  Complex.add(double x)
Complex.subtractReal(double x) as  Complex.subtract(double x)

Not covered:

Complex.multiplyImaginary(double x)
Complex.divideImaginary(double x)
Complex.addImaginary(double x)
Complex.subtractImaginary(double x)
Complex.subtractFromReal(double x)
Complex.subtractFromImaginary(double x)


I am going through Complex now to fix code coverage and make it in line 
with the C.99 standard. I will push all the config changes with the 
update to Complex. Should be done be end of today.


Then we can look at fixing checkstyle and PMD.




Regards,
Gilles


It is possible in C:

#include 
#include 
#include 
#include 

int main( int argc, const char* argv[] ) {
   double a = 5.0;
   complex double z = 1 + 3 * I;
   complex double z2 = a - z;
   printf("%.17g + %.17g i\n", creal(z2), cimag(z2));
   complex double z3 = z - a;
   printf("%.17g + %.17g i\n", creal(z3), cimag(z3));
}

And C++:

#include 
#include 
#include 

int main( int argc, const char* argv[] ) {
   const double a = 5.0;
   std::complex z(1, 3);
   std::complex z2 = a - z;
   printf("%.17g + %.17g i\n", z2.real(), z2.imag());
   std::complex z3 = z - a;
   printf("%.17g + %.17g i\n", z3.real(), z3.imag());
}

Both yield:

4 + -3 i
-4 + 3 i

Note that Complex::add(double) exists. This needs no alternative as the 
addition of the real to the real component is commutative:

double a
complex z
a + z = z + a

The subtraction is not commutative (as shown above):
a - z != z - a

So given the Complex has a subtract(double) it would be fair to have a 
subtractFrom(double).

The complex subtraction is also not commutative:

complex y
complex z
y - z != z - y

But in this case you can achieve the same with the API by swapping the 
arguments.


This would avoid:

Complex a = …;
double b = …;
Complex c  = Complex.ofCartesian(b - a.real(), a.imag());

This is clear.


Complex d  = Complex.ofReal(b).subtract(a).conj();

This even more, but, I get it, with 3 instantiations instead of 1.


With

Complex a = …;
double b = …;
Complex c  = a.subtractFrom(b);

Looks ambiguous...  But if it's standard naming.

Regards,
Gilles



[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf 


[2] http://www.open-std.org/JTC1/SC22/WG14/www/standards 


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



Re: [numbers] Bug in complex multiply + divide + isNaN

2019-11-07 Thread Gilles Sadowski
Hello.

> > [...]
> >
> >>
> >> Also looking at Complex it would benefit from:
> >>
> >>public Complex subtractFrom(double minuend) {
> >>return new Complex(minuend - real, imaginary);
> >>}
> >
> > Is it part of the "standard"?
> > IMHO, it's fairly confusing, as nothing in the name indicates
> > that the operation only applies to the real part.
>
> The same applies for the add(real) and subtract(real) methods.
>
> What is confusing is the unconventional reverse ordering of z.subtractFrom(a) 
> == a - z. I’m not happy about it but the javadoc can explain the outcome.

Actually, what confuses me is that the above equality does not hold:
  double a = 5;
  Complex z = Complex.of(1, 3);
  Complex z2 = z.subtractFrom(a);
would yield
  4 + 3 i
whereas
  Complex z2 = Complex.of(a).subtract(z);
would yield
  4 - 3 i

Regards,
Gilles

> It is possible in C:
>
> #include 
> #include 
> #include 
> #include 
>
> int main( int argc, const char* argv[] ) {
>   double a = 5.0;
>   complex double z = 1 + 3 * I;
>   complex double z2 = a - z;
>   printf("%.17g + %.17g i\n", creal(z2), cimag(z2));
>   complex double z3 = z - a;
>   printf("%.17g + %.17g i\n", creal(z3), cimag(z3));
> }
>
> And C++:
>
> #include 
> #include 
> #include 
>
> int main( int argc, const char* argv[] ) {
>   const double a = 5.0;
>   std::complex z(1, 3);
>   std::complex z2 = a - z;
>   printf("%.17g + %.17g i\n", z2.real(), z2.imag());
>   std::complex z3 = z - a;
>   printf("%.17g + %.17g i\n", z3.real(), z3.imag());
> }
>
> Both yield:
>
> 4 + -3 i
> -4 + 3 i
>
> Note that Complex::add(double) exists. This needs no alternative as the 
> addition of the real to the real component is commutative:
>
> double a
> complex z
> a + z = z + a
>
> The subtraction is not commutative (as shown above):
> a - z != z - a
>
> So given the Complex has a subtract(double) it would be fair to have a 
> subtractFrom(double).
>
> The complex subtraction is also not commutative:
>
> complex y
> complex z
> y - z != z - y
>
> But in this case you can achieve the same with the API by swapping the 
> arguments.
>
> >
> >>
> >> This would avoid:
> >>
> >> Complex a = …;
> >> double b = …;
> >> Complex c  = Complex.ofCartesian(b - a.real(), a.imag());
> >
> > This is clear.
> >
> >> Complex d  = Complex.ofReal(b).subtract(a).conj();
> >
> > This even more, but, I get it, with 3 instantiations instead of 1.
> >
> >>
> >> With
> >>
> >> Complex a = …;
> >> double b = …;
> >> Complex c  = a.subtractFrom(b);
> >
> > Looks ambiguous...  But if it's standard naming.
> >
> > Regards,
> > Gilles
> >
> >>
> >>>
> 
> 
>  [1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf 
>  
> 
>  [2] http://www.open-std.org/JTC1/SC22/WG14/www/standards 
>  
> >>>

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



Re: [numbers] Bug in complex multiply + divide + isNaN

2019-11-07 Thread Gilles Sadowski
Hi.

Le jeu. 7 nov. 2019 à 01:48, Alex Herbert  a écrit :
>
>
>
> > On 7 Nov 2019, at 00:34, Gilles Sadowski  wrote:
> >
> > 2019-11-07 1:03 UTC+01:00, Alex Herbert  > >:
> >>
> >>
> >>> On 6 Nov 2019, at 23:17, Eric Barnhill  >>> > wrote:
> >>>
> >>> +1 on all suggestions. Thanks, Alex.
> >>
> >> I’ve borrowed the checkstyle, PMD and spot bugs config from commons-rng. I
> >> updated the parent to 49 and updated the travis build script to run the
> >> check goal instead of creating reports.
> >
> > I had updated the PMD configuration (copying from [RNG] and removing
> > references to specific classes) this afternoon.
>
> I did not really change the PMD config. Just a bump of the PMD versions.
>
> However pmd:check was never run so this is now in the default goal and run on 
> travis.

I used to review this after
  $ mvn site site:stage

> Travis currently has a problem with the length of the log file being too long 
> as Maven downloads the entire internet. So I’m trying a fix for that.
>
> >
> >>
> >> This requires disabling checkstyle:check and pmd:check from failing.
> >> Checkstyle errors were previously listed. PMD has the following errors:
> >>
> >> [INFO] You have 23 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-core/target/pmd.xml
> >> [INFO] You have 16 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-complex/target/pmd.xml
> >> [INFO] You have 30 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-complex-streams/target/pmd.xml
> >> [INFO] You have 30 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-primes/target/pmd.xml
> >> [INFO] You have 13 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-quaternion/target/pmd.xml
> >> [INFO] You have 42 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-fraction/target/pmd.xml
> >> [INFO] You have 3 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-angle/target/pmd.xml
> >> [INFO] You have 192 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-gamma/target/pmd.xml
> >> [INFO] You have 35 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-combinatorics/target/pmd.xml
> >> [INFO] You have 14 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-arrays/target/pmd.xml
> >> [INFO] You have 10 PMD violations. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-field/target/pmd.xml
> >> [INFO] You have 1 PMD violation. For more details see:
> >> /Users/ah403/git/commons-numbers/commons-numbers-rootfinder/target/pmd.xml
> >
> > Yes, those should be fixed (and perhaps some could be considered
> > as false positives).
>
> I’m not planning on doing a lot of fixing. With RNG I made most of the PMD 
> issues go away with some rule tweaking.

Quite fine; many of these "violations" tends to be nits (like "Do not
reuse method
arguments") and should not be blocking a release; the issue were in Commons Math
forever without anyone bothering.

>
> I will fix checkstyle though. This can be semi automated.

I can help fixing those, once you've pushed you pending changes to "master".

Gilles

> >> [...]

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