Re: Why does we still need StrictMath?

2022-05-08 Thread Martin Desruisseaux

Le 08/05/2022 à 14:15, Victor Williams Stafusa da Silva a écrit :


Was that using Java 17+, which included JEP 306 delivered?

No, but my understanding is that JEP 306 does not apply to Math versus 
StrictMath behavior. In my understanding, the strictfp keyword was only 
about the use of extended exponent value set in Pentium 80 bits floating 
point values. It impacts the behavior of arithmetic operations + - * /, 
but my (maybe wrong) understanding is that it does not impact which 
processor instruction is used for implementing Math.sin, cos, etc.


    Martin




Re: Why does we still need StrictMath?

2022-05-08 Thread Martin Desruisseaux

Le 08/05/2022 à 10:56, Andrew Haley a écrit :

Some targets (x86, in particular) have intrinsics (log, trig) that are 
faster than StrictMath and also more accurate. StrictMath is not about 
accuracy, but cross-architecture down-to-the-last bit reproducibility. 
Whether we still need that reproducibility is, I suppose, something 
for debate.


In production code, maybe not. But in test code (e.g. using JUnit), when 
the program does a lot of trigonometric operations (e.g. map 
projections), I have meet cases where a test was successful on a machine 
but failed on another machine. The systematic use of StrictMath in all 
JUnit test code ensure that the difference in behavior is not in the 
test code, so we can focus our debugging effort on the main code.


    Martin




Re: Discussion about Java Floating Point?

2022-03-15 Thread Martin Desruisseaux

Hello A.Z.

As Raffaello said, Java arithmetic does not have any more problem than 
C/C++ when using IEEE 754. The "proof" of contrary is only an illusion 
due to the rounding behavior of C/C++ output routines, as demonstrated 
by Raffaello's code. Maybe some C/C++ code use Intel extended precision 
arithmetic (80 bits instead of 64 bits), but it only pushes the problem 
further, it still not an exact representation of decimal numbers. Exact 
representation of 0.1 using base 2 is mathematically impossible, no 
matter the language (it is a periodic number in base 2).


    Regards,

        Martin




Re: Questions about enhancement and Correction to Java OpenJDK Floating Point?

2022-03-14 Thread Martin Desruisseaux

Hello A.Z

As far as I know, the difference in output that you observed between 
Java and C/C++ is not caused by a difference in floating-point 
computation, but in a difference in the way numbers are rounded by the 
"printf" command. Java has a policy of showing all significant digits, 
while C "printf" has a policy of rounding before printing. In my 
opinion, this is more dangerous because it hides what really happen in 
floating-point computation.


The following statement is not entirely true when using finite floating 
point precision:



(…snip…) It is a mathematical fact that, for
consistent, necessary and even fast term, 10% of 10% must
always precisely be 1%, and by no means anything else.


Above statement can be true only when using base 10 or some other bases. 
We could also said "It is a mathematical fact that 1/3 of 1/3 must 
always precisely be 1/9 and nothing else", but it can not be represented 
fully accurately with base 10. It can be represented fully accurately 
with base 3 however. There will always be examples that work in one base 
and not in another, and natural laws has no preference for base 10. I 
understand that base 10 is special for financial applications, but for 
many other applications (scientific, engineering, rendering…) base 2 is 
as good as any other base. I would even argue that base 10 can be 
dangerous because it gives a false sense of accuracy: it gives the 
illusion that rounding errors do not happen when testing with a few 
sample values in base 10 (like 10% of 10%), while in reality rounding 
errors continue to exist in the general case.


    Martin




Re: RFR: 8261880: Change nested classes in java.base to static nested classes where possible [v2]

2021-05-20 Thread Martin Desruisseaux
On Wed, 17 Feb 2021 16:38:03 GMT, Сергей Цыпанов 
 wrote:

>> Non-static classes hold a link to their parent classes, which in many cases 
>> can be avoided.
>
> Сергей Цыпанов has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   8261880: Remove static from declarations of Holder nested classes

Just for information there is similar issues in 
`javax.imageio.metadata.IIOMetadataFormatImpl` class in the `java.desktop` 
module.

-

PR: https://git.openjdk.java.net/jdk/pull/2589


Re: RFR: 8180352: Add Stream.toList() method

2020-11-06 Thread Martin Desruisseaux

Le 06/11/2020 à 19:00, Alan Snyder a écrit :
(…snip…) But a question that deserves ongoing review is whether Java 
should support immutable collections using a separate type hierarchy 
(…snip…).


Maybe an alternative way (admittedly more difficult) to have immutable 
collections without introducing new interfaces could be to take 
inspiration from the C++ "const" keyword? Especially since in Java, 
"const" is already a reserved keyword, just not used yet.


I realize that it would be a difficult task: how to handle private 
fields that are just caches in a const object; where to add the "const" 
keyword in existing JDK API; how to make such change in a backward 
compatible way (e.g. when a legacy code overrides a "const" method). I 
do not have any expectation. But given the inconvenient of alternatives, 
I wonder if there is some research about the long-term feasibility of a 
"const" semantic in Java? If it was the case, then maybe it would be 
better to not add immutable collection interfaces in Java for now.


    Regards

        Martin




Re: RFR: 8180352: Add Stream.toList() method

2020-11-03 Thread Martin Desruisseaux

Hello

Le 03/11/2020 à 21:30, fo...@univ-mlv.fr a écrit :

You know that you can not change the implementation of 
Collectors.toList(), and you also know that if there is a method 
Stream.toList(), people will replace the calls to 
.collect(Collectors.toList()) by a call to Stream.toList() for the 
very same reason (…snip…)


Would they would be so numerous to do this change without verifying if 
the specifications match? (on my side I do read the method javadoc). But 
even if we worry about developers not reading javadoc, the argument 
could go both ways: they could assume that all Stream methods accepts 
null and not read that Stream.toList() specifies otherwise.


    Martin




Re: Feature suggestion: Add static equals methods to Float and Double

2019-01-09 Thread Martin Desruisseaux
Le 08/01/2019 à 19:55, Hans Boehm a écrit :
> The IEEE standard does say that for quiet NaNs, the value (or one of them)
> "should" be preserved by most operations on the quiet NaN. I have not heard
> of implementations violating this for anything other than the "quiet" bit.
> Thus I don't immediately see why it would be problematic to encode an
> explicitly programmer-introduced error cause in the remaining bits (as
> opposed to relying on hardware-generated patterns). I have not seen
> non-testing code that does so, but I would be mildly surprised if it
> doesn't exist somewhere.

I confirm that such code exist and are used in production for 15 years
at least in the GeoTools and Apache Spatial Information System (SIS)
projects. Earth Observation data are often images mixing measurement
values with different kind of missing values. So above-cited projects
perform computation on float primitive types where, for example:

  * Real values are Sea Surface Temperatures values in °C.
  * One NaN bit pattern stands for values missing because the sea was
hidden by a cloud.
  * Another NaN bit pattern stands for values missing because the pixel
is over a land.
  * Another NaN bit pattern stands for values missing because the remote
sensor did not fly over that area.
  * etc.

Actually those data are typically encoded as integers in some file
format where each missing value is associated to a different color
(clouds in white, lands in brown, etc.). But they are converted to float
values for performing calculations (e.g. applying the "gradient
magnitude" operator provided by Java Advanced Imaging library), then
converted back to integers for displaying purpose with
java.awt.image.RenderedImage. It allows the use of mathematical formulas
without special checks for missing values, and still preserve the lands,
clouds, etc. masks in the resulting image. I have never seen yet a lost
of information encoded in quiet NaN values (e.g. I have not seen a "NaN
for land" mutated to a "NaN for cloud"), except if an arithmetic
operation is applied on two different NaN bit patterns.

    Martin




Re: Thought on multiplicity of properties in Java

2018-09-18 Thread Martin Desruisseaux
Hello Rémi

Le 18/09/2018 à 00:28, fo...@univ-mlv.fr a écrit :

> - theoretically, the covariance is defined in term of sub-typing,
> trying to widen it's definition may have unintended consequences that
> need studying.
>
Agree that it would require studying. But we have a general guidance,
which is that a subtype must obey to all constraints declared in the
parent type. The Java type covariance follow that rule: we can use a
more specific return type in a subclass, but not the converse since it
would broke the constraint defined by the return type in the parent
class. The proposed "multiplicity covariance" follows the same rule: a
subclass would be allowed to define a more specific multiplicity, but
the converse is not allowed. For example a [0…1] multiplicity defined in
the parent class can be restricted to the [1…1] multiplicity in a
subclass, but can not be changed to [0…2] or any other value outside the
[0…1] range.


> - technically, we can implement whatever conversions we want because
> the "convariance conversion" is implemented using brige, but we may
> not implement that the "covariance conversion" using bridges in the
> future if by example we do some kind of reification of the type
> arguments, so this may hamper the possible futures of Java.
>
The proposed "multiplicity covariance conversion" would be implemented
using bridges too. However I admit that I lack knowledge on the
consequences in a context of reification.


> - the conversion from Optional to a List is not a conversion already
> defined by the JLS, this need also to be specified because there is no
> reason to limit this conversion to only the covariance case, by
> example if you have an Optional named opt, this statement
> List list = opt; should compile. This means that you have to
> formally defines the conversion and perhaps the reverse conversion
> too, Optional opt2 = (Optional)list; at that point you
> are not backward compatible with the current JLS because this code
> currently always throws a CCE.
>
In the "multiplicity covariance" proposal, the set of conversions that
are allowed is determined by the above-cited rule that multiplicity in
return value can only be restricted - not widened. By labelling Foo =
[1…1], Optional = [0…1] and Collection = [0…∞], we can build
the set of allowed conversions. Those conversions would not be performed
by casts, but by bridge methods (in widening direction because the
bridge methods implement the methods defined by parent class):

  * [0…1] ← [1…1]: Optional.of(value);
  * [0…∞] ← [1…1]: List.of(value);
  * [0…∞] ← [0…1]: if empty Collections.emptyList() otherwise
List.of(value);

Martin




Re: Thought on multiplicity of properties in Java

2018-09-17 Thread Martin Desruisseaux
Hello Rémi

Thanks for your reply.

Le 17/09/2018 à 00:54, Remi Forax a écrit :

> The Java spec limit covariance to subtyping relationship only (there
> is no covariance between primitive types, or between a primitive type
> and it's corresponding wrapper), so you can not use Java to implement
> overriding of UML properties with different multiplicity. But if you
> generate the bytecode instead of generating Java code to generate the
> interfaces, you are not limited by the Java spec, so you can generate
> the bridge methods you want.
>
Yes I know. My question was if "multiplicity covariance" was something
that may be worth considering at the Java language level for some future
version of the specification. This is not a request to do so, only an idea.

    Regards,

        Martin




Thought on multiplicity of properties in Java

2018-09-15 Thread Martin Desruisseaux
I’m deriving Java interfaces from the UML of ISO 19111 international
standard, and a though come to my mind. This is not a request for
changing anything in the Java language now, I’m just wondering if this
is something worth to be considered for the future. This proposal would
require javac to handle Optional and maybe Collection method
return types in a special way, but would not require JVM change in my
understanding.

Sometime a property is optional in a parent class, but become mandatory
in some subclasses. In UML, the [0…1] multiplicity in parent class
become restricted to [1…1] multiplicity in subclasses. I wonder if javac
could do a special case for catching this model as below. Allow to override:

class Parent {
    Optional getFoo();
}

with:

class Child extends Parent {
    @MaybeSomeAnnotationMakingIntentClear
    @Override
    Foo getFoo();
}

Those two methods differ only by the return type, which I think is
allowed at the JVM level. In the Child class, javac would generate the
following synthetic method:

@Override
final Optional getFoo() {
    return Optional.of(getFoo());  // Invoke the getFoo() method that 
return Foo.
}

Subclasses of Child can override only the method returning Foo, not
Optional. In UML parlance, the [0…1] multiplicity can be restricted
to [1…1] but the converse is not allowed (this is the same reasoning
than method return type covariance in Java, applied to multiplicity
instead than type). Invocation of getFoo() on Parent class would invoke
the methods returning Optional, while invocation of getFoo() on
Child class would invoke the method returning Foo. Whether the following
should be a compiler error or not is an open question:

Child a = ...;
Optional foo = a.getFoo();

Something similar could be done for method returning Collection
too, if we consider those methods as properties having a [0…∞]
multiplicity which can be restricted to [0…1] or [1…1] multiplicity in
subclasses. In summary, Java already has type covariance and I wonder if
it could be extended to "multiplicity covariance" with javac handling
Collection as [0…∞], Optional as [0…1] and Foo as [1…1]. I'm
of course not asking for any action; just curious if it is worth to put
on a list of possible future Java evolutions.

    Regards,

        Martin




Re: Java Float and Double changes, BigDecimal maths class, BigDecimal operators?

2018-03-06 Thread Martin Desruisseaux
Le 06/03/2018 à 05:48, A Z a écrit :

> Citation about problems with Java floating point:
> https://people.eecs.berkeley.edu/~wkahan/JAVAhurt.pdf

This paper is about complex numbers, operation overloading, handling of
NaN, /etc./ I don't think that they are making an argument for decimal
arithmetic.


> People absolutely need decimal accuracy, and not floating point
> approximations
>
Float and double are accurate in base 2, which is as good as base 10 for
scientific and engineering applications (nature does not have a
preferred base - our use of base 10 is only because human have 10
fingers). Base 10 is useful in some cases like financial applications,
but those ones already have their own representation (e.g. integer count
of 1/1000 of cents). When numbers are measurements, values like 0.1 are
approximation anyway, no matter if using base 2 or base 10.

IEEE754 float and double types have hardward acceleration in modern CPU.
Consequently IEEE754 is used not only in Java, but also in other
languages like C/C++. The C language may give an impression of accuracy
because printf can round the last digits, but the actual accuracy is
still the same than Java.

    Martin




Re: JEP 238: Multi-Version JAR Files

2015-02-27 Thread Martin Desruisseaux
Le 27/02/15 16:47, Florian Weimer a écrit :
> Maybe I misunderstood the multi-version JAR files proposal, but I
> thought that the assumption there is that there are actual *source*
> files which use newer features of the platform.
>
> I really don't think this tooling support will provide sufficient
> enticement to developers to maintain separate 7/8/9 source branches of
> their libraries.

Some projects do, while admittedly maybe only a minority. For example
Apache Spatial Information System (SIS) has JDK6, JDK7 and JDK8
branches. Development is done on JDK8, then ported down to JDK6, which
is the target JDK platform for current releases [1].

Martin

[1] http://sis.apache.org/branches.html



Re: ConcurrentModificationException in java.util.ServiceLoader (not a multi-thread issue)

2015-02-24 Thread Martin Desruisseaux
Hello Peter

Le 24/02/15 13:49, Peter Levart a écrit :
> You could synchronize on the entire loop and just copy over the
> service objects to another collection (say ArrayList).

Right, but I would like to keep the laziness instantiation behaviour.


> If you really must combine laziness of constructing service objects
> with concurrent iterations, you can wrap the ServiceLoader.iterator()
> with the following:
>
> public class BufferedConcurrentIterable implements Iterable {
> (...snip...)

Many thanks for your help. This is indeed what I did yesterday :-). But
given that the current ServiceLoader behaviour results in random
ConcurrentModificationException in some multi-threads environments, this
can mislead the users who believe that they have a synchronization error
in their own code before they realize that the issue is in ServiceLoader
itself.

Martin




Re: ConcurrentModificationException in java.util.ServiceLoader (not a multi-thread issue)

2015-02-24 Thread Martin Desruisseaux
Le 24/02/15 09:09, Alan Bateman a écrit :

> Right, it has never supported multiple iterators but as it's an
> Iterable then it should unless specified otherwise. So I think this is
> a bug (although one could argue that the usage is unusual, almost a
> mis-use).

One use case is that in a multi-thread environment, this bug implies
that it is not sufficient to synchronize all direct and indirect
(through Iterator) usages of ServiceLoader. We must synchronize the
entire iteration loop for preventing other threads to start a new
iteration before we finished the current one. This can be annoying if
the work to do between two calls to Iterator.hasNext() / next() is long.
Sometime it is not possible to synchronize the entire loop if we do not
control the iteration (i.e. if we advance in the iterator only when the
user invokes some method). The later case can be a problem even in
mono-thread application.


> Not clear whether it's worth doing anything about it now, this is
> because ServiceLoader is going to change very significantly soon when
> it is re-specified to work with modules. I'll create a bug anyway to
> track it anyway.

Thanks. The fact that ServiceLoader was going to be modified for Jigsaw
is precisely the reason why I was wondering if it was worth to
investigate more now.

Martin




ConcurrentModificationException in java.util.ServiceLoader (not a multi-thread issue)

2015-02-23 Thread Martin Desruisseaux
Hello all

java.util.ServiceLoader does not seem to support usage of a second
Iterator in the middle of a previous iteration. The attached Java file
provides two simple tests with a ServiceLoader iterating over two
elements. The first test creates two iterators and invokes their
hasNext() / next() methods in the following order:

  * Iterator 1
  * Iterator 2
  * Iterator 1
  * Iterator 2  -  unexpected end of iteration here.

The second test creates two iterators and invoke the hasNext() methods
on both iterators before to invoke their next() methods. This result is
the following exception (tested on 1.8.0_31-b13):

Exception in thread "main" java.util.ConcurrentModificationException
at 
java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:711)
at 
java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:744)
at 
java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:742)
at java.util.ServiceLoader$1.next(ServiceLoader.java:479)
at test.ServiceLoaderTest.test2(ServiceLoaderTest.java:47)
at test.ServiceLoaderTest.main(ServiceLoaderTest.java:12)

(note: to run the test, the attached test.ServiceLoaderTest file needs
to be in the META-INF/services/ directory). I found a Stackoverflow
thread mentioning this issue 4 years ago [1], but apparently without
solution. Should I look for a patch, or is the current behaviour
considered okay (in which case I would suggest to warn the users in the
Javadoc)?


Martin


[1] 
http://stackoverflow.com/questions/2593777/serviceloader-double-iterator-issues


test.ServiceLoaderTest$I1
test.ServiceLoaderTest$I2


Re: Re: Time to retire System.runFinalizersOnExit?

2015-01-29 Thread Martin Desruisseaux
Le 29/01/15 04:43, Mandy Chung a écrit :
> Throwing UOE is intentional so that applications depending on existing
> behavior will be modified not to use this deprecated method.   Making
> it a no-op makes it harder to diagnose for applications depending on
> the finalizers to be invoked on exit to free resources.  I opt to
> throw UOE (or remove the method that will leave it for another
> discussion some other day).

Maybe one or two years ago, I saw a similar discussion about "almost
removing" a method from the JDK. Some proposed to define a new
annotation in addition to @Deprecated, something like @Retired, which
would cause the javac and javadoc compilers to behave as if the method
has been removed while the method would still be available at runtime
for a transition period. Would it be something worth to consider? (or
alternatively an optional argument to @Deprecated?)

Martin



Re: JDK 9 RFR of 4477961: java.lang.Math.toDegrees(double) could be optimized

2014-09-23 Thread Martin Desruisseaux
Hi Brian

Le 23/09/14 00:34, Brian Burkhalter a écrit :
> I created an alternate webrev using compile-time constants per your 
> suggestion:
>
> http://cr.openjdk.java.net/~bpb/4477961/webrev.01/

On a very minor formatting detail, the change in StrictMath has a
misplaced empty line (before the RADIANS_TO_DEGREES constant, while it
should be after).

Also, would it be worth to remove the "private" modifier in
StrictMath.DEGREES_TO_RADIANS and StrictMath.RADIANS_TO_DEGREES, and
have Math.toDegrees and Math.toRadians to use the StrictMath constants
instead than duplicating them? It would reduce slightly the size of the
Math.class file by avoiding 2 field declarations.

Martin




Re: Replace concat String to append in StringBuilder parameters

2014-08-21 Thread Martin Desruisseaux
I had a random look at the Webrev for TreeModelEvent.java and saw the
following new code:

sb.append(Integer.toString(childIndices[counter]))

Wouldn't the following be slightly more efficient?

sb.append(childIndices[counter])

since Integer.toString(int) creates a temporary char[] array later
copied in the StringBuilder, while StringBuilder.append(int) writes
directly in the buffer internal array.


Martin



Le 21/08/14 14:53, Wang Weijun a écrit :
> I filed a bug at
>
>https://bugs.openjdk.java.net/browse/JDK-8038277
>
> Webrev in 3 parts at
>
>http://cr.openjdk.java.net/~weijun/8038277/client/webrev.00
>http://cr.openjdk.java.net/~weijun/8038277/core/webrev.00/
>http://cr.openjdk.java.net/~weijun/8038277/extra/webrev.00/
>
> --Max



Re: 8020860: cluster Hashtable/Vector field updates for better transactional memory behaviour

2014-04-16 Thread Martin Desruisseaux
Hello all

Le 15/04/14 18:14, Mike Duigou a écrit :
> I have updated the webrev with what I hope is the final form:
>
> http://cr.openjdk.java.net/~mduigou/JDK-8020860/1/webrev/

The first changes in the javadoc contains "{@code #keys keys}" and
"{@code #elements elements}". I presume that you mean {@link} instead of
{@code}?

Martin



Re: Time to put a stop to Thread.stop?

2013-05-15 Thread Martin Desruisseaux

Le 15/05/13 10:05, David Holmes a écrit :
There is a huge difference between blowing away a complete process 
with kill and having a single thread starting to propagate an async 
exception, unwinding its stack and executing finally blocks with 
completely broken state invariants.


Given the risk, what about a mechanism similar to the one which 
currently hides the Sun internal packages from the compilation phase but 
not yet from the runtime phase? Would it be acceptable to have 'javac' 
and 'javadoc' woking as if the 'Thread.stop(Throwable)' method did not 
existed anymore, while having the method still working (for now) at 
runtime for existing libraries? Maybe with an annotation yet stronger 
than @Deprecated.


Martin



Unnecessary array copy in AbstractStringBuilder.indexOf(String)?

2012-11-19 Thread Martin Desruisseaux

Hello all

I noticed that AbstractStringBuilder.indexOf(String, int) is implemented 
as below:


public int indexOf(String str, int fromIndex) {
return String.indexOf(value, 0, count,
  str.toCharArray(), 0, str.length(), 
fromIndex);

}

The call to str.toCharArray() creates a copy of the String.value char[] 
array. This copy doesn't seem necessary since the above 
String.indexOf(...) method doesn't modify the array content. Shouldn't 
AbstractStringBuilder passes directly the reference to the String 
internal array instead, maybe using package-privated access to the array?


Admittedly the cloned array is usually small, but the call to 
indexOf(String, int) is often done in a loop.


Martin



Re: String.subSequence and CR#6924259: Remove offset and count fields from java.lang.String

2012-06-26 Thread Martin Desruisseaux

Le 26/06/12 20:10, Mike Duigou a écrit :

  StringBuilder.append(string.substring(lower, upper));
by:
  StringBuilder.append(string, lower, upper);

This would seem to be a good refactoring regardless of the substring 
implementation as it avoids creation of a temporary object.


The rational was that the performance advantage of using 
System.arraycopy(...) instead than a loop over CharSequence.charAt(int) 
may compensate the cost of creating a temporary object. I would not be 
surprised if the former was faster than the later for large substrings 
despite the temporary object creation. However it may not be true 
anymore now that substring(...) performs a copy. Of course this would 
need to be verified with benchmark...


Martin



Re: String.subSequence and CR#6924259: Remove offset and count fields from java.lang.String

2012-06-26 Thread Martin Desruisseaux
If String.substring(int, int) now performs a copy of the underlying 
char[] array and if there is no String.subSequence(int, int) providing 
the old functionality, maybe the following implications should be 
investigated?



StringBuilder.append(...)

Since, in order to avoid a useless array copy, the users may be advised 
to replace the following pattern:


  StringBuilder.append(string.substring(lower, upper));
by:
  StringBuilder.append(string, lower, upper);

would it be worth to add a special-case in the 
AbstractStringBuilder.append(CharSequence, int, int) implementation for 
the String case in order to reach the efficiency of the 
AbstractStringBuilder.append(String) method? The later copies the data 
with a single call to System.arraycopy, as opposed to the former which 
invoke CharSequence.charAt(int) in a loop.



Integer.parseInt(...)

There was a thread one years ago about allowing Integer.parseInt(String) 
to accept a CharSequence.


http://mail.openjdk.java.net/pipermail/core-libs-dev/2012-April/thread.html#9801

One invoked reason was performance, since the cost of calling 
CharSequence.toString() has been measured with the NetBeans profiler as 
significant (assuming that the CharSequence is not already a String) 
when reading large ASCII files. Now if the new String.substring(...) 
implementation copies the internal array, we may expect a performance 
cost similar to StringBuilder.toString(). Would it be worth to revisit 
the Integer.parseInt(String) case - and similar methods in other wrapper 
classes - for allowing CharSequence input?


Martin



Le 23/06/12 00:15, Mike Duigou a écrit :

I've made a test implementation of subSequence() utilizing an inner class with 
offset and count fields to try to understand all the parts that would be 
impacted. My observations thus far:

- The specification of the subSequence() method is currently too specific. It 
says that the result is a subString(). This would no longer be true. Hopefully 
nobody assumed that this meant they could cast the result to String. I know, 
why would you if you can just call subString() instead? I've learned to assume 
that somebody somewhere does always does the most unexpected thing.
- The CharSequences returned by subSequence would follow only the general 
CharSequence rules for equals()/hashCode(). Any current usages of the result of 
subSequence for equals() or hashing, even though it's not advised, would break. 
We could add equals() and hashCode() implementations to the CharSequence 
returned but they would probably be expensive.
- In general I wonder if parsers will be satisfied with a CharSequence that 
only implements identity equals().
- I also worry about applications that currently do use subSequence currently 
and which will fail when the result is not a String instance as String.equals() 
will return false for all CharSequences that aren't Strings. ie. CharSequence 
token =ine.subSequence(line, start, end); if (keyword.equals(token)) ... This 
would now fail.

At this point I wonder if this is a feature worth pursuing.

Mike




Re: Integer.parseInt

2012-04-12 Thread Martin Desruisseaux

Le 12/04/12 10:57, Benedict Elliott Smith a écrit :

I think in this case it is reasonable to leave it to the user to ensure
that the input remains consistent for the duration of the call. It can be
documented if necessary, but as I say I think all imperative methods come
with that caveat by definition. Calling the toString() method as a solution
is really no better than asking the user to do the same, albeit a little
neater; the only reason a CharSequence method would be preferred is that
you can avoid unnecessary object allocation. For a very lightweight method
like parseInt, this can dramatically reduce the impact of making the call.


We faced this issue in our project when parsing OpenStreetMap data (an open 
source alternative to Google Map). The amount of integers to parse is so large 
that the calls to the 'toString()' method has been identified as a significant 
bottleneck by the NetBeans profiler. We tried a copy of the 'parseInt' method 
with the String argument replaced by CharSequence, and noticed a significant 
performance gain.


Martin



Strange or obsolete @see tags in some exception javadoc

2012-01-12 Thread Martin Desruisseaux

Hello all

Some widely-used exceptions which were defined in the old Java 1.0 days have 
strange or obsolete javadoc "@see" tags:


http://docs.oracle.com/javase/7/docs/api/java/lang/IllegalArgumentException.html
IllegalArgumentException declares "@see Thread#setPriority(int)". Why is 
Thread.setPriority(int) so special in regard to IllegalArgumentException?


http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html
NumberFormatException declares "@see Integer#toString()". Shouldn't it be "@see 
Integer#parseInt(String)" instead?


http://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.html
NoSuchElementException declares the legacy "@see Enumeration#nextElement()", but 
does not declare the "@see Iterator#next()" replacement.


Martin



Re: StrictMath performance improvement not ported to Math?

2011-11-22 Thread Martin Desruisseaux

Hello Joe

Le 22/11/11 04:20, Joe Darcy a écrit :

3) In if statements, replaced:

(a == 0.0d) && (Double.doubleToLongBits(a) == negativeZeroDoubleBits)
by
(Double.doubleToLongBits(a) == negativeZeroDoubleBits)

since the later implies the former.


The performance properties of the two versions of the code may differ 
depending on the frequency of zeros in the input and the cost of the bitwise 
conversion operation. I'd prefer to leave the code logic as-is in absence of 
some benchmarking that showed a helpful difference.
I presumed that Double.doubleToRawLongBits(a) - I forgot the "Raw" in my 
previous post - was very cheap after HotSpot intrinsics (which exist according 
vmSymbols.hpp). If my old memory from 80286 assembler still have some value, it 
would have simply be a matter of comparing the value from the same memory 
address using a different machine instruction. But obviously this is only 
supposition, today picture is very different and I have no benchmark for 
confirming or refuting my supposition…




I'd prefer to see a webrev with:

* All min/max logic from StrictMath moved into math, including for the 
integral types int and long

* All StrictMath min/max methods delegating to their Math counterpart
Done. I updated the webrev at the same URL: 
http://webrev.geomatys.com/Math/min_max/index.html
The new Math code is a verbatim copy-and-paste from StrictMath, including the 
formatting.


I also made StrictMath.abs methods delegating to their Math counterpart, after 
making sure that the code was really identical. After this change, the only 
remaining duplicated code is toDegrees and toRadians. For those two methods, I 
added a comment saying why StrictMath dos not delegate to Math for them (because 
the StrictMath methods have the "strictfp" modifier - but this modifier is easy 
to miss, so a comment may be a worthy safety).



* Verification all java/lang/Math and java/lang/StrictMath regression tests 
still pass
I quicky tried, but it seems to be a bit tricky for me since I'm on a MacOS 
machine. Maybe it will be easier when the MacOS port project will be completed...


Martin



StrictMath performance improvement not ported to Math?

2011-11-18 Thread Martin Desruisseaux

Hello all

On December 1, 2010, "darcy" committed a slight performance improvement to the 
StrictMath.min/max methods with floating point arguments (commit 8aabca72877c). 
The calls to the doubleToLongBits(double) method were replaced by calls to the 
doubleToRawLongBits(double) method, and similarly for the float type. Since the 
call to doubleToLongBits was used only in order to determine if an argument was 
negative zero, and since NaN can not map to the bits pattern of -0.0, the extra 
cost of collapsing all NaN values to a single canonical NaN (which is the only 
difference between doubleToLongBits and doubleToRawLongBits) was unnecessary.


However this improvement has not been ported from StrictMath to Math; the more 
widely-used Math class still invokes the (presumed) slower 
doubleToLongBits(double) method. Actually it appears that most Math / StrictMath 
method implementations delegate to the other class: some Math methods delegates 
to StrictMath (mostly the methods backed by native code), and some StrictMath 
methods delegate to Math (mostly the methods implemented in pure-Java). The 
min/max methods are an exception; their implementation is copied in both 
classes. Maybe this explain why the code was updated in only one class and not 
the other?


In the patch submitted below, I propose the following changes:

1) Ported the doubleToLongBits --> doubleToRawLongBits changes from StrictMath 
to Math.


2) Replaced StrictMath implementations by calls to Math, in order to reduce the 
risk that the code of only one class is updated in the future.


3) In if statements, replaced:

  (a == 0.0d) && (Double.doubleToLongBits(a) == negativeZeroDoubleBits)
by
  (Double.doubleToLongBits(a) == negativeZeroDoubleBits)

since the later implies the former.

4) Moved the check for (a != a) from the method beginning to the last statement, 
which is tested only if (a <= b) were false rather than tested unconditionally 
in every cases. I'm not sure if it make a real performance difference however.


Webrev link: http://webrev.geomatys.com/Math/min_max/index.html

Regards,

Martin



Re: Miscellaneous minor patches: javadoc typos, javac warnings, etc.

2011-11-10 Thread Martin Desruisseaux

Le 10/11/11 16:24, Joe Darcy a écrit :
The Float and Double changes look fine.  I don't know why the constructors 
were coded up that way;


Maybe because the Float(String) / Double(String) constructors were coded in Java 
1.0, while the parseFloat(String) / parseDouble(String) methods were added (at 
least in public API) only in Java 1.2 and someone forgot to revisit the 
constructors at that time...


Martin



Re: Miscellaneous minor patches: javadoc typos, javac warnings, etc.

2011-11-09 Thread Martin Desruisseaux

Hello Phil

Le 09/11/11 18:37, Phil Race a écrit :

Please do register on 2d-dev and propose the 2D changes there.

Registration done, I will post in a few minutes.


The hashcode change
definitely needs discussion, I think there may be views on the NaN comparison 
as my

understanding is that this is supposed to always be not equal.
The proposed change is consistent with the java.lang.Double.equals(Object) 
behavior. It seems to me the only way to be compliant with the reflexivity 
contract documented in Object.equals javadoc, apart doing a "if (other == this) 
return true" check. Maybe whatever full compliance with Object.equals is 
strongly desired or not can be a question for the core group? I would like to 
note that incomplete compliance may be a risk when AffineTransform (or any other 
object) is used as keys in Hashtable: in current implementation, if an 
AffineTransform object with at least one NaN value is added in a Hashtable, it 
is impossible to remove it by a call to Hashtable.remove(Object) (we can still 
remove it by Iterator.remove()). (Note: my example uses Hashtable instead of 
HashMap because HashMap has a clever implementation that check for object 
references before to invoke Object.equals, which invalidate my argument. However 
not all implementations are that safe).



PS this is such an unrelated set of changes, I am not sure it should be under 
one CR, even for 2D.
Actually this is 8 distinct change sets, but webrev merged all my change sets in 
a single one. Since it is the first time I'm using webrev, I'm probably not 
using it in the right way. But I still have the 8 distinct changes set on my 
local Mercurial clone, so I can probably recreate new webrev pages if I learn 
how to use webrev better...


Regards,

Martin



java.awt.geom.AffineTransform.hashCode() is inconsistent with equals(Object)

2011-05-20 Thread Martin Desruisseaux

Hello all

I realize that this is a Java2D bug, but given that it is a simple 
equals(Object)/hashCode() implementation issue maybe this list is still relevant...


AffineTransform.hashCode() method is inconsistent with equals(Object) when some 
'double' values are 0.0 values of opposite sign. The reason is that 'hashCode()' 
uses 'doubleToLongBits(double)' which return different values for positive and 
negative zero, while 'equals(Object)' uses '==' which treat -0.0 as equals to 
+0.0. I verified in latest JDK 7 source code that this bug is still present.


Trivial test case:

import java.awt.geom.AffineTransform;
public class AffineBug {
public static void main(String[] args) {
AffineTransform tr1 = new AffineTransform();
AffineTransform tr2 = new AffineTransform();
tr2.translate(-0.0, 0);
System.out.println("hashCode 1: " + tr1.hashCode());
System.out.println("hashCode 2: " + tr2.hashCode());
System.out.println("equals: " + tr1.equals(tr2));
}
}


Current AffineTransform.equals(Object) implementation is:

public boolean equals(Object obj) {
if (!(obj instanceof AffineTransform)) {
return false;
}
AffineTransform a = (AffineTransform)obj;
return ((m00 == a.m00) && (m01 == a.m01) && (m02 == a.m02) &&
(m10 == a.m10) && (m11 == a.m11) && (m12 == a.m12));
}

Possible fix would be (assuming appropriate static import):

public boolean equals(Object obj) {
if (!(obj instanceof AffineTransform)) {
return false;
}
AffineTransform a = (AffineTransform)obj;
return ((doubleToLongBits(m00) == doubleToLongBits(a.m00))
&& (doubleToLongBits(m01) == doubleToLongBits(a.m01))
&& (doubleToLongBits(m02) == doubleToLongBits(a.m02))
&& (doubleToLongBits(m10) == doubleToLongBits(a.m10))
&& (doubleToLongBits(m11) == doubleToLongBits(a.m11))
&& (doubleToLongBits(m12) == doubleToLongBits(a.m12)));
}


Note that this have the side effect of considering NaN values as equal.

Similar bug affect also Point2D and Rectangle2D (I did not checked the other 
geometric classes).


Regards,

Martin



java.util.Objects.requireNonNull: an opportunity for NullArgumentException?

2011-02-23 Thread Martin Desruisseaux

Hello all

I apologize if this question was already debated previously. I just wonder: 
since JDK 7 defines an Object.requireNonNull(…) method for explicit checks of 
argument value, does the Project-Coin expert group has considered the addition 
of an explicit NullArgumentException extends NullPointerException for making 
clear that this exception is the result of an argument check rather than some 
bug hidden in the middle of a code?


Some kind of NullArgumentException seems a common addition in many libraries 
built on top of JDK. To name just a few from a quick Google search:


http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/NullArgumentException.html
http://www.croftsoft.com/library/code/javadoc/core/com/croftsoft/core/lang/NullArgumentException.html
http://api.dpml.net/dpml/1.1.0/net/dpml/transit/NullArgumentException.html
http://www.geotoolkit.org/apidocs/org/geotoolkit/util/NullArgumentException.html

A blog:
http://closingbraces.net/2007/02/26/nullargumentexception/

Regards,

Martin