Next: , Previous: objects booleans, Up: objects

### 12.5 Fixnum objects

Fixnums are “small” exact integers which fit in a single machine word: if the word size is 4, 30 bits are used for fixnum representation; else the word size is 8 and 61 bits are used for fixnum representation. On a 32-bit platform, 30 bits are available to store the number:

```     (greatest-fixnum)       ⇒ +536870911
(expt 2 29)             ⇒ +536870912
(- (expt 2 29) 1)       ⇒ +536870911

(least-fixnum)          ⇒ -536870912
(- (expt 2 29))         ⇒ -536870912
```
• With machine words 32-bit wide, which means the word size is 4 bytes, the representation of a fixnum is:
```           30 bits fixnum representation
|........................|00

|-----|-----|-----|------+--|
byte3 byte2 byte1   byte0
```

the two least significant bits are set to zero: this “tags” the machine words which embed fixnums.

• With machine words 64-bit wide, which means the word size is 8 bytes, the representation of a fixnum is:
```                   61 bits fixnum representation
|...............................................|000

|-----|-----|-----|-----|-----|-----|-----|-----+---|
byte7 byte6 byte5 byte4 byte3 byte2 byte1  byte0
```

the three least significant bits are set to zero: this “tags” the machine words which embed fixnums.

The fixnums tag is `00` on 32-bit platforms and `000` on 64-bit platforms; given the symbols:

`fx_shift`
Set to the number of bits in the tag.
`fx_scale`
Set to the number of bytes in a machine word.

the value is selected in such a way that:

```     length_in_bytes = number_of_words *  fx_scale
= number_of_words *  wordsize
= number_of_words << fx_shift
```

this allows us, for example, to take the fixnum representing the number of items in a vector and consider it directly as size of the vector's data area in bytes.

##### Basic operations

Given an exact integer stored in a `long` value with the right amount of bits, we encode a fixnum as follows:

```     long    the_value  = ...;
ikptr   the_fixnum = (ikptr)(the_value << fx_shift);
```

and we decode it as follows:

```     ikptr   the_fixnum = ...;
long    the_value  = (long)(the_fixnum >> fx_shift);
```

to verify if a `ikptr` is a fixnum we do:

```     ikptr   the_fixnum = ...;

if (fx_tag == ((long)the_fixnum & fx_mask))
it_is_a_fixnum();
else
it_is_not();
```

it is better to use the convenience macros described below.

— Macro: fx_tag 0

The fixnums tag.

— Macro: fx_shift

The number of bits in the fixnums tag. It is the amount of bits we have to left–shift a machine word to encode its value as fixnum.

Bit mask used to isolate the tag bits of a fixnum.

##### Convenience preprocessor macros

Examples:

```     long int  N = 123L;
ikptr     P = IK_FIX(N);
long int  M = IK_UNFIX(P);
```
— Preprocessor Macro: ikptr IK_FIX (num)
— Preprocessor Macro: ikptr fix (num)

Convert a small exact integer in the correct range for a fixnum, into a `ikptr` value. num is cast to `long int`.

NOTE The macro `fix` is defined only in the internal header file and its usage is deprecated.

— Preprocessor Macro: long IK_UNFIX (ikptr ref)
— Preprocessor Macro: long unfix (ikptr ref)

Convert an `ikptr` value holding a fixnum into a fixnum of type `long int`.

NOTE The macro `unfix` is defined only in the internal header file and its usage is deprecated.

— Preprocessor Macro: int IK_IS_FIXNUM (ikptr ref)

Expand to true if ref is an `ikptr` embedding a fixnum. It just tests if the least significant bits in the tag are set to zero.