https://github.com/clj-commons/primitive-math
for the discerning arithmetician
https://github.com/clj-commons/primitive-math
Last synced: 3 months ago
JSON representation
for the discerning arithmetician
- Host: GitHub
- URL: https://github.com/clj-commons/primitive-math
- Owner: clj-commons
- Created: 2013-06-07T20:02:43.000Z (about 12 years ago)
- Default Branch: master
- Last Pushed: 2023-07-28T21:09:04.000Z (almost 2 years ago)
- Last Synced: 2024-05-22T04:41:03.085Z (about 1 year ago)
- Language: Clojure
- Size: 75.2 KB
- Stars: 169
- Watchers: 9
- Forks: 15
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.adoc
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
[](https://clojars.org/org.clj-commons/primitive-math)
[](https://cljdoc.org/d/org.clj-commons/primitive-math)
[](https://circleci.com/gh/clj-commons/primitive-math)### About
Clojure's numeric tower is useful, but it can put a lot of steps between you and simple arithmetic. Unfortunately, while Clojure will warn you when reflection is required to invoke a function, it will **not** warn you when reflection is required to perform math. The only reliable way to discover whether you're calling `clojure.lang.Number.add(Object, Object)` or `clojure.lang.Number.add(long, long)` is to use a profiler or decompiler.
Or, you can just bypass Clojure's math operators altogether.
In the `clj-commons.primitive-math` namespace, there are equivalents for every arithmetic operator and comparator that will give a reflection warning if it cannot compile down to a simple, predictable, unboxed mathematical operation.
```clojure
clj-commons.primitive-math> (set! *warn-on-reflection* true)
true
clj-commons.primitive-math> (+ 3 3)
6
clj-commons.primitive-math> (defn adder [x] (+ 1 x))
;; gives a reflection warning
clj-commons.primitive-math> (defn adder [^long x] (+ 1 x))
;; no reflection warning
clj-commons.primitive-math> (+ 3.0 3)
;; gives a reflection warning AND throws an exception
```To support operations on both `long` and `double` types without any reflection, these operators are defined as macros. This means they cannot be used as higher-order functions:
```clojure
clj-commons.primitive-math> (apply + [1 2 3])
;; throws a 'cannot take value of macro' exception
```In practice, it's usually preferable to import the namespace with a prefix, and use `p/+` and `p/==` operators alongside the normal Clojure functions. However, if in a particular namespace you never need to use higher-order operators, you can call `(primitive-math/use-primitive-operators)` to swap out the Clojure operators for their primitive equivalents. This can be reversed, using `(primitive-math/unuse-primitive-operators)`.
##### Notes
Pre-1.0.0 versions of primitive-math used a single-segment namespace. This causes problems for Graal and clj-easy. For 1.0.0, everything was copied under the `clj-commons` namespace. The code is effectively identical, however, so unless you are using Graal, you don't need to make any changes. If you *are* using Graal, make sure you only require the `clj-commons.*` namespaces to avoid issues.
### Usage
```clojure
;;; Lein
[org.clj-commons/primitive-math "1.0.1"];;; deps.edn
org.clj-commons/primitive-math {:mvn/version "1.0.1"}
```### An exhaustive list of operators
```clojure
+
-
*
/ ;; aliased as 'div'
inc
dec
rem
==
not==
zero?
<=
>=
<
>
min
max
bool-and
bool-or
bool-not
bool-xor
true?
false?
bit-and
bit-or
bit-xor
bit-not
bit-shift-left ;; aliased as '<<'
bit-shift-right ;; aliased as '>>'
unsigned-bit-shift-right ;; aliased as '>>>'
byte
short
int
float
long
double
byte->ubyte
ubyte->byte
short->ushort
ushort->short
int->uint
uint->int
long->ulong
ulong->long
reverse-short
reverse-int
reverse-long
```Full documentation can be found at [cljdoc](https://cljdoc.org/d/org.clj-commons/primitive-math).
### License
Copyright © 2016 Zachary Tellman
Distributed under the [MIT License](http://opensource.org/licenses/MIT).