clr

Srayan Jana 2024-07-14T00:01:26.282709Z

is clojureclr the same languare as on the jvm?

seancorfield 2024-07-14T05:45:26.021829Z

Essentially, yes. There interop stuff is different -- obviously, since it's .NET interop on the CLR but Java interop on the JVM.

seancorfield 2024-07-14T05:46:21.744639Z

And you can write cross-platform code in .cljc files that run on the CLR, the JVM, and in the browser/on node.js.

seancorfield 2024-07-14T05:47:21.824409Z

The main difference right now is tooling, which is a lot more mature for JVM Clojure but that's being worked on so the CLR version will soon be fairly similar.

Mark Pebblestream 2024-07-14T21:47:18.711199Z

What's the recommended way to take the ceiling of a BigDecimal? (BigDecimal/Rescale 0.09M 0 clojure.lang.BigDecimal+RoundingMode/Ceiling) => 0M

dmiller 2024-07-19T16:31:09.897619Z

I think I have a fix. It's just a small change in Rescale. Details available upon request. For starters, I always have trouble figuring out what is the correct behavior in Quantize, Rescale , and Round. For example, if you have 0.06M and you Rescale with Ceiling to an exponent of 1, it seems that the answer should be 1E+1M. Looking carefully at the specification, the answer would be 0, but because we lost some digits, Ceiling says we must increment the coefficent by one. And the exponent is required to be 1. So there we are. Here are my test cases run with the modified code. Preliminaries:

(import  '[clojure.lang BigDecimal BigDecimal+RoundingMode])
(def mhu BigDecimal+RoundingMode/HalfUp)
(def mc BigDecimal+RoundingMode/Ceiling)
(def mf BigDecimal+RoundingMode/Floor)

;; a little helper -- given a BigDecimal and a rounding mode, do a rescale with several different exponents
(defn f [bd mode exps] (map #(BigDecimal/Rescale bd % mode) exps))
Doing some tests with half-up:
(f 0.4M mhu [-3 -2 -1 0 1])   ; => (0.400M 0.40M 0.4M 0M 0E+1M)
(f 0.6M mhu [-3 -2 -1 0 1])   ; => (0.600M 0.60M 0.6M 1M 0E+1M)
(f 0.04M mhu [-3 -2 -1 0 1])  ; => (0.040M 0.04M 0.0M 0M 0E+1M)
(f 0.06M mhu [-3 -2 -1 0 1])  ; => (0.060M 0.06M 0.1M 0M 0E+1M)
Those look okay, I think. We see rounding up in the appropriate places. Let's try with Ceiling:
(f 0.4M mc [-3 -2 -1 0 1])   ; => (0.400M 0.40M 0.4M 1M 1E+1M)
(f 0.6M mc [-3 -2 -1 0 1])   ; => (0.600M 0.60M 0.6M 1M 1E+1M)
(f 0.04M mc [-3 -2 -1 0 1])  ; => (0.040M 0.04M 0.1M 1M 1E+1M)
(f 0.06M mc [-3 -2 -1 0 1])  ; => (0.060M 0.06M 0.1M 1M 1E+1M)
the 0 exponent cases in the last two lines were the ones giving us a problem in our tests of the old code earlier in this thread. You suggested two more test cases:
(BigDecimal/Rescale -0.1M 0 mc)  ; => -1M
 (BigDecimal/Rescale -0.1M 0 mf)  ; => 0M
And my test suite is running green. (I have about 4000 tests on BigDecimal. Just not many on Ceiling.) I'll have this up in the next alpha release. If you want to compile from source before then, I can tell you edit to make. (I probably won't have a commit to the repo for another day. I have to do some other cleanup first.)

dmiller 2024-07-19T17:22:16.668919Z

Modified BigDecimal code now in repo.

Mark Pebblestream 2024-07-19T17:24:09.994789Z

Nice! Quite a subtle fix. Thanks!

dmiller 2024-07-19T17:24:51.536019Z

Apparently I should have trusted the magic of BigDecimal.Round.

Mark Pebblestream 2024-07-16T14:33:26.467279Z

Sounds good. Here's another ceiling test case:

(BigDecimal/Rescale -0.1M 0 clojure.lang.BigDecimal+RoundingMode/Ceiling) ; => -1M
And floor:
(BigDecimal/Rescale -0.1M 0 clojure.lang.BigDecimal+RoundingMode/Floor) ; => 0M

dmiller 2024-07-15T20:52:33.863479Z

My fourth guess would have been what you wrote. My first three guesses would have been wrong. It's been a long time since I worked on this code. I've forgotten most of it. Not just the code. Despite having implemented it, I remained mystified by some operations. BigDecimal.Rescale certainly falls in that category. There are tests in the test suite that deal with Rescale -- over 400, actually. However, they all have rounding mode = HalfUp. It is possible there is a problem with Ceiling. I'll do some digging.

👍 1
dmiller 2024-07-15T22:19:54.367439Z

I'm not sure what the exact problem is. It's something to do with precision vs scale. A quick experiment:

; define modes to use
(def mc (clojure.lang.BigDecimal+RoundingMode/Ceiling))
(def mhu (clojure.lang.BigDecimal+RoundingMode/HalfUp))

; check out something that should work just fine
(BigDecimal/Rescale 123.45M 0 mhu)  ; => 123M
(BigDecimal/Rescale 123.55M 0 mhu)  ; => 124M
(BigDecimal/Rescale 123.45M 0 mc)   ; => 124M
(BigDecimal/Rescale 123.55M 0 mc)   ; => 124M

; check out values less than  1 -- this first set looks okay
(BigDecimal/Rescale 0.45M 0 mhu)  ; => 0M
(BigDecimal/Rescale 0.55M 0 mhu)  ; => 1M
(BigDecimal/Rescale 0.45M 0 mc)   ; => 1M
(BigDecimal/Rescale 0.55M 0 mc)   ; => 1M

; let's drop our precision -- still okay
(BigDecimal/Rescale 0.4M 0 mhu)   ; => 0M
(BigDecimal/Rescale 0.6M 0 mhu)   ; => 1M
(BigDecimal/Rescale 0.4M 0 mc)    ; => 1M
(BigDecimal/Rescale 0.6M 0 mc)    ; => 1M

; drop down a decimal place, and suddenly we are in trouble
(BigDecimal/Rescale 0.04M 0 mhu)  ; => 0M
(BigDecimal/Rescale 0.06M 0 mhu)  ; => 0M
(BigDecimal/Rescale 0.04M 0 mc)   ; => 0M  ** BAD
(BigDecimal/Rescale 0.06M 0 mc)   ; => 0M  ** BAD
I'm really going to have to dig into the spec to figure this one out. Y'all are welcome to join in: https://speleotrove.com/decimal/decarith.pdf Could be a problem in Rescale, though it works for all my test cases -- until now!

👍🏿 1