Unsigned comparison of numbers in Clojure?

I am trying to write an image processing library in Clojure, but while writing tests I ran into a problem.

Image data is saved as a 2D array of integers that are signed (Java and, by extension Clojure, do not have unsigned integers). I have a function to get a pixel for a given pair of coordinates. My test of this function looks something like this:

(is (= (get-pixel image 0 (dec width)) 0xFFFF0000)) 

That is, if the pixel at (0, width-1) is red. The problem is that get-pixel returns a signed int, but Clojure treats 0xFFFF0000 as long. In this case, getting the pixel returns -65536 (0xFFFF0000 in hexadecimal format), and Clojure checks if it is equal to 4294901760.

Now I have several options. I could rewrite the test using an integer interpretation of the hexadecimal number as a decimal number (-65536), but I think this makes the purpose of the test less clear. I could write a function to convert a negative number into a positive long, but this is an additional level of complexity. The easiest way is to simply bitwise between the two numbers and see if it has changed, but it still seems more complicated than it should be.

Is there any built-in way to force 0xFFFF0000 to evaluate to a signed integer rather than a long one, or to perform a bitwise comparison of two arbitrary numbers? The int function does not work, since the number is too large to be represented as a signed int.

Thanks!

+4
source share
2 answers

In clojure 1.3, there is an unchecked-int function that simply takes the bottom four bytes and makes them int:

 user> (unchecked-int 0xffff0000) -65536 

It's a little sad that clojure does not allow you to enter alphabetic numbers of different sizes - here we make the Java equivalent (int)0xffff0000L .

+4
source

What version of clojure are you using? Initial processing has been changed quite a bit in version 1.3. I was experimenting a bit, and I seem to get different results than you describe.

 user=> (int 0xFFFF0000) IllegalArgumentException Value out of range for int: 4294901760 clojure.lang.RT.intCast (RT.java:1093) user=> (long 0xFFFF0000) 4294901760 user=> *clojure-version* {:major 1, :minor 3, :incremental 0, :qualifier nil} 

If you are using 1.3, you can use the long function. You can also manipulate your data with ByteBuffer and process bytes a bit more directly, although you will never get the level of control you would have with C.

0
source

Source: https://habr.com/ru/post/1387483/


All Articles