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.