Performance of numeric operations

Kawa can generally do a pretty good job of generating efficient code for numeric operations, at least when it knows or can figure out the types of the operands.

The basic operations +, -, and * are compiled to single-instruction bytecode if both operands are int or long. Likewise, if both operands are floating-point (or one is floating-point and the other is rational), then single-instruction double or float instructions are emitted.

A binary operation involving an infinite-precision integer and a fixed-size int or long is normally evaluated by expanding the latter to integer and using integer arithmetic. An exception is an integer literal whose value fits in an int or long - in that case the operation is done using int or long arithmetic.

In general, integer literals have amorphous type. When used to infer the type of a variable, they have integer type:

(let ((v1 0))
  ... v1 has type integer ... )

However, a literal whose value fits in the int or long range is implicitly viewed int or long in certain contexts, primarily method overload resolution and binary arithmetic (as mentioned above).

The comparison functions <, <=, =, >, and => are also optimized to single instriction operations if the operands have appropriate type. However, the functions zero?, positive?, and negative? have not yet been optimized. Instead of (positive? x) write (> x 0).

There are a number of integer division and modulo operations. If the operands are int or long, it is faster to use quotient and remainder rather than div and mod (or modulo). If you know the first operand is non-negative and the second is positive, then use quotient and remainder. (If an operand is an arbitrary-precision integer, then it dosn’t really matter.)

The logical operations bitwise-and, bitwise-ior, bitwise-xor, bitwise-not, bitwise-arithmetic-shift-left, bitwise-arithmetic-shift-right are compiled to single bitcode instructions if the operands are int or long. Avoid bitwise-arithmetic-shift if the sign of the shift is known. If the operands are arbitrary-precision integer, a library call is needed, but run-time type dispatch is avoided.