Re: bigint and biginteger

2014-06-09 Thread Plínio Balduino
Thank you, Mark and Mike

Awesome explanation and examples

Plínio

On Sat, Jun 7, 2014 at 8:46 AM, Mike Fikes mikefi...@me.com wrote:
 Thanks for the historical perspective, puzzler!

 In addition to performance considerations, Clojure Programming points to an
 inconsistency between hash codes for longs and BigIntegers as a motivation.

 Using the example number from that excellent book on Clojure 1.5.1 (on Java
 8, FWIW), I can cause this:

 #{6948736584 (biginteger 6948736584)}

 ; = #{6948736584 6948736584}


 #{6948736584 (bigint 6948736584)}

 ; = IllegalArgumentException Duplicate key: 6948736584
 clojure.lang.PersistentHashSet.createWithCheck (PersistentHashSet.java:56)


 (System/getProperty java.version)

 ; = 1.8.0_05


 (clojure-version)

 ; = 1.5.1


 On Clojure 1.6, thankfully both fail, even in the face of the inconsistency
 between .hashCode implementations. If that essentially addresses the 2nd
 rationale for introducing a special BigInt class, maybe with both things
 being fixed with Java 8 and Clojure 1.6 BigInteger could come back as the
 sole arbitrary precision representation of ℤ.

 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: bigint and biginteger

2014-06-07 Thread Mike Fikes
Thanks for the historical perspective, puzzler! 

In addition to performance considerations, *Clojure Programming* points to 
an inconsistency between hash codes for longs and BigIntegers as a 
motivation. 

Using the example number from that excellent book on Clojure 1.5.1 (on Java 
8, FWIW), I can cause this:

#{6948736584 (biginteger 6948736584)}

; = #{6948736584 6948736584}


#{6948736584 (bigint 6948736584)}

; = IllegalArgumentException Duplicate key: 6948736584  
clojure.lang.PersistentHashSet.createWithCheck (PersistentHashSet.java:56)

(System/getProperty java.version)

; = 1.8.0_05


(clojure-version)

; = 1.5.1


On Clojure 1.6, thankfully both fail, even in the face of the inconsistency 
between .hashCode implementations. If that essentially addresses the 2nd 
rationale for introducing a special BigInt class, maybe with both things 
being fixed with Java 8 and Clojure 1.6 BigInteger could come back as the 
sole arbitrary precision representation of ℤ.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


bigint and biginteger

2014-06-06 Thread Plínio Balduino
Hi there.

I read old threads and I didn't understand why Clojure has bigint and
biginteger.

Could you explain better?

Thank you

Plínio

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: bigint and biginteger

2014-06-06 Thread Mark Engelberg
Java has a class called java.math.BigInteger.  Clojure's biginteger simply
typecasts to the built-in java class.

Several years ago, Clojure exclusively used java.math.BigInteger to handle
integers larger than longs.  Back then, Clojure's arithmetic operators
would automatically overflow, so if you added to longs and the sum was
larger than a long, you'd get back a BigInteger.

Then, Clojure changed so that arithmetic overflows would throw an error
rather than automatically promoting to BigInteger.  Users who wanted
overflow were given two options:

Option 1: Use auto-promoting arithmetic operators (e.g., +' and *').
Option 2: Seed your arithmetic with a BigInteger so that all the arithmetic
would be contaminated by the BigInteger, and all the numbers would be
cast into BigIntegers before the arithmetic happened.

So, for example, if you wrote a loop-recur version of summing all the
numbers from 1 to n:

(defn sum [n]
  (loop [acc 0
 n n]
(if (zero? n) acc (recur (+ acc n) (dec n)

This could theoretically overflow for extremely large values of n, so if
you want to handle that, choice 1 is:

(defn sum [n]
  (loop [acc 0
 n n]
(if (zero? n) acc (recur (+' acc n) (dec n)

Choice 2 is:

(defn sum [n]
  (loop [acc (biginteger 0)
 n n]
(if (zero? n) acc (recur (+ acc n) (dec n)

What happened is that people who made choice #2 started complaining of
performing problems.  Turned out that if you converted everything to
bigintegers, but most of your numbers were actually in the long range, you
were paying a pretty significant performance penalty.

So, the Clojure group decided to make a faster BigInteger, which they
called BigInt, and numbers like 0N are just shorthand for (bigint 0).
Basically, as long as your BigInt falls within long range, internally it is
stored and manipulated as a long.  This minimizes the performance penalty
for using BigInts with numbers that can be represented as longs. The
penalty is fairly comparable to the penalty of using boxed Longs versus
primitive longs.  Only if you go outside of that range do you start paying
the performance for the more complex BigInteger representation.

You can see
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/BigInt.java
for the source code of how BigInt is represented as a long if it can, and
otherwise a BigInteger.

The main downside of this is that BigInt lacks the richness of the
java.math.BigInteger API.  I think at one time there was a plan to make
BigInt support the exact same API as java.math.BigInteger, but it never
happened.  So, you need to explicitly convert to BigInteger if you want to
use those methods.

Interestingly, I just tried to type up a few functions to demonstrate the
slowness of java.math.BigInteger versus boxed Longs for numbers that fall
within the long range, and I couldn't come up with any example that showed
a significant difference.

This makes me wonder:

*Is it possible that Java 8 made performance improvements to
java.math.BigInteger that render clojure.lang.BigInt obsolete?*
If so, that would be wonderful -- Clojure could go back to just using the
BigInteger class and we'd get both good performance and the richer API.




On Fri, Jun 6, 2014 at 6:06 PM, Plínio Balduino pbaldu...@gmail.com wrote:

 Hi there.

 I read old threads and I didn't understand why Clojure has bigint and
 biginteger.

 Could you explain better?

 Thank you

 Plínio

 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with
 your first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en
 ---
 You received this message because you are subscribed to the Google Groups
 Clojure group.
 To unsubscribe from this group and stop receiving emails from it, send an
 email to clojure+unsubscr...@googlegroups.com.
 For more options, visit https://groups.google.com/d/optout.


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
Clojure group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.