### 28.2 Optimized integer arithmetic and integer vector access

This section describes ways to perform certain operations as efficiently as possible, including vector access and raw 32-bit arithmetic. Additionally in 64-bit LispWorks, raw 64-bit arithmetic is possible.

#### 28.2.1 Typed aref vectors

You can make vectors of certain element types which allow the most efficient access possible when compiled with suitable optimize qualities.

To do this:

1. Make a vector with make-typed-aref-vector.
2. Access the vector using typed-aref and `(setf typed-aref)` with a type argument of double-float, `float`, single-float, int32, `(unsigned-byte `n`)` or `(signed-byte `n`)` where n = 8, 16 or 32.
3. Additionally, in 64-bit LispWorks the types `(unsigned-byte 64)` and `(signed-byte 64)` are supported.

4. Compile the access with `safety 0` (and for float types, `float 0`) and a constant type.

See typed-aref for more details and examples.

Efficient access to foreign arrays is also available. See `fli:foreign-typed-aref` in the LispWorks Foreign Language Interface User Guide and Reference Manual .

#### 28.2.2 Fast 32-bit arithmetic

The INT32 API provides a way to perform optimal raw 32-bit arithmetic. Note that, unlike Lisp integer types, this is modulo 2^32 like the C `int` type.

The INT32 symbols are all in the `system` package.

The Lisp type int32 reads 32 bits of memory, like `(signed-byte 32)`, but the data is in int32 format for use with the INT32 API.

##### 28.2.2.1 Optimized and unoptimized INT32 code

When optimized correctly, the intermediate int32 objects are not constructed.

In unoptimized code, sequences of operations like

``` (sys:int32+ (sys:int32- a b) (sys:int32- c d))```

will generate intermediate int32 objects for the results of the subtraction, but the compiler can optimize these away because it knows that the function int32+ consumes int32 objects.

Note: the INT32 API is not designed to optimize `sys:int32` objects passed as arguments.

##### 28.2.2.2 The INT32 API

The INT32 API contains the type int32, a vector type simple-int32-vector and accessor, functions to convert int32 to and from integer, some constant int32 values, and a full range of operators for mod 2^32 arithmetic.

You can find all these by evaluating

``` (apropos "INT32" "SYSTEM" t)```

For details for each, see the entries starting with int32 in The SYSTEM Package.

##### 28.2.2.3 INT32 Optimization

The optimization works safely but without boxing when possible. You need

``` (optimize (float 0))```

to get the optimization. This `float` level affects whether INT32 operations are optimized. This declaration must be placed at the start of a function (not on an inner `let` or `locally` form).

In this example the `safety` level assures a second optimization in `fli:foreign-typed-aref`:

`(defun incf-signed-byte-32 (ptr index)`
`  (declare (optimize (safety 0) (float 0))`
`           (type fixnum index))`
`  (setf (fli:foreign-typed-aref 'sys:int32 ptr index)`
`        (sys:int32-1+ (fli:foreign-typed-aref 'sys:int32 `
`                                              ptr index)))`
`  ;; return ptr, since otherwise the int32 would`
`  ;; need to be boxed to return it`
`  ptr)`

#### 28.2.3 Fast 64-bit arithmetic

The INT64 API provides a way to perform optimal raw 64-bit arithmetic. Note that, unlike Lisp integer types, this is modulo 2^64 like the C `long` `long` or `int64` types.

The INT64 symbols are all in the `system` package.

The Lisp type int64 reads 64 bits of memory, like `(signed-byte 64)`, but the data is in int64 format for use with the INT64 API.

##### 28.2.3.1 Optimized and unoptimized INT64 code

When optimized correctly, the intermediate int64 objects are not constructed.

In unoptimized code, sequences of operations like

``` (sys:int64+ (sys:int64- a b) (sys:int64- c d))```

will generate intermediate int64 objects for the results of the subtraction, but the compiler can optimize these away because it knows that the function int64+ consumes int64 objects.

Note: the INT64 API is not designed to optimize `sys:int64` objects passed as arguments.

##### 28.2.3.2 The INT64 API

The INT64 API contains the type int64, a vector type simple-int64-vector and accessor, functions to convert int64 to and from integer, some constant int64 values, and a full range of operators for mod 2^64 arithmetic.

You can find all these by evaluating

``` (apropos "INT64" "SYSTEM" t)```

For details for each, see the entries starting with int64 in The SYSTEM Package.

##### 28.2.3.3 INT64 Optimization

INT64 optimization occurs only in 64-bit LispWorks. The INT64 API is not optimized in 32-bit LispWorks.

The optimization works safely but without boxing when possible. You need

``` (optimize (float 0))```

to get the optimization. This `float` level affects whether INT64 operations are optimized. This declaration must be placed at the start of a function (not on an inner `let` or `locally` form).

In this example the `safety` level assures a second optimization in `fli:foreign-typed-aref`:

`(defun incf-signed-byte-64 (ptr index)`
`  (declare (optimize (safety 0) (float 0))`
`           (type fixnum index))`
`  (setf (fli:foreign-typed-aref 'sys:int64 ptr index)`
`        (sys:int64-1+ (fli:foreign-typed-aref 'sys:int64 `
`                                              ptr index)))`
`  ;; return ptr, since otherwise the int64 would`
`  ;; need to be boxed to return it`
`  ptr)`

#### 28.2.4 Integer vector access

octet-ref and base-char-ref (and their setters) are provided to allow efficient access to simple vectors of element type `(unsigned-byte 8)` or `base-char` (that is, simple-base-strings) in the same code.

Other vector types are accepted, but for these specific string and binary vector types octet-ref and base-char-ref match what `aref` and `(setf aref)` do except that they always take and return the same value/result type, and they are also more efficient than `aref`.

Use octet-ref and base-char-ref according to whether you work with elements of type `integer` or `base-char`.

LispWorks User Guide and Reference Manual - 20 Sep 2017