### 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.

Additionally, in 64-bit LispWorks the types `(unsigned-byte 64)` and `(signed-byte 64)` are supported.

3. 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 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 47 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 47 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 - 01 Dec 2021 19:30:25