Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Clojure by
recategorized ago by

Is there support for BigDecimal promotion in the +', *', etc. clojure.core functions?

When I run the following code in the REPL:

(* 2 Double/MAX_VALUE)     ;; ##Inf, Doesn't auto-promote as was expected.
(*' 2 Double/MAX_VALUE)    ;; ##Inf, Expected that it would auto promote.

Following cases also didn't work:

(*' Double/MAX_VALUE 2)        ;; ##Inf, Moving around the arguments.
(*' 2.0 Double/MAX_VALUE)      ;; ##Inf, Using a Double literal instead.
(*' Double/MAX_VALUE 2.0)      ;; ##Inf
(*' Double/MAX_VALUE 2.0M)     ;; ##Inf, Using a BigDecimal literal instead.
(*' 2.0M Double/MAX_VALUE)     ;; ##Inf

I decided to check the Clojure compiler source for promotion, and based on my limited understanding of the code I see that DoubleOps is using the implementation of addP of OpsP abstract class (which just calls the normal add function) while there is one present for LongOps which can be found here.


Is this a bug? And if yes, I would like to work on the fix and I'll check the Development page of Clojure to do the needfull.

by
edited by
Adding more context as I keep diving deeper.

I see that we have this static overload of the [addP](https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Numbers.java#L1526-L1528) function in the [Numbers](https://github.com/clojure/clojure/blob/6a4ba6aedc8575768b2fff6d9c9c7e6503a0a93a/src/jvm/clojure/lang/Numbers.java#L19) class that would need to be removed since currently the compiler resolves the above calls to this (or similarly defined static functions for the `double` type argument permutations in the `Numbers` class) function.

I managed to get `inc'` working by having it promote `(inc' Double/MAX_VALUE)` to `BigDecimal`.

```clj
$ java -jar clojure.jar   
                                                                                                                                         
Clojure 1.13.0-master-SNAPSHOT

user=> (inc' Double/MAX_VALUE)
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369M

user=> (class (inc' Double/MAX_VALUE))
java.math.BigDecimal
```

--------------------------------------------------------------------------------------------------------------------------------------------

I'll be pushing my changes as I make them here: https://github.com/shantanu-sardesai/clojure/tree/bug/14752-automatic-promotion , feel free to critique them! Just a FYI, still working on getting the other function implementation updated and having the Clojure tests clearing.

1 Answer

0 votes
ago by
selected ago by
 
Best answer

I think this is not a bug and is by design - the auto-promotion operators only have promotion semantics for integer arguments, not for floats.

The only relevant reference page here is https://clojure.org/reference/data_structures#_longs - it's important to note that this is in a header called "Longs" and only mentions promotion for integer types:

Clojure provides a set of alternative math operators suffixed with an
apostrophe: +', -', *', inc', and dec'. These operators auto-promote
to BigInt upon overflow, but are less efficient than the regular math
operators.

I went back and did some digging from when numerics were overhauled (Clojure 1.3). The design docs from this time can be found in these wayback links that provide more context and align with the semantics above:

The promotion op docstrings are currently not very helpful in understanding this (see CLJ-2923 ).

ago by
Would there be interest in supporting BigDecimal in the promoting functions? Seems pretty helpful.
ago by
I assume there was good reason to not do that or it would have been included, but I have not found an answer to that in docs I've reviewed, so will have to be a question for Rich.
...