1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
|
.\" Copyright 2024 Andrew V.Kosteltsev (kx@radix-linux.su)
.\"
.\"
.TH LIBMPU 7 "December 27, 2024" "libmpu" "libmpu Programmer's Manual"
.SH NAME
libmpu \- Math Processor Unit Library (libmpu).
.SH DESCRIPTION
The library is designed as a processor emulator with a set of registers and flags that are set according
to the results of the operations performed. The set of integer functions contains arithmetic and logical
operations, as well as all types of shift operations. Basic trigonometric functions are implemented for
real and complex numbers.
.PP
Bit capacity is limited to \fB65536\fP bits for arithmetic operations and \fB16384\fP bits
for trigonometry. The limitations are due to the order of the approximation series.
.SH Data formats
The library supports integer, real and complex types. Variables are stored in byte arrays.
.sp
.SS Integer numbers
The \fBlibmpu.h\fP header file defines constants that represent the number of bytes
to store integer variables:
.nf
.sp
#define NB_I8 1
#define NB_I16 2
#define NB_I32 4
#define NB_I64 8
#define NB_I128 16
#define NB_I256 32
#define NB_I512 64
#define NB_I1024 128
#define NB_I2048 256
#define NB_I4096 512
#define NB_I8192 1024
#define NB_I16384 2048
#define NB_I32768 4096
#define NB_I65536 8192
#define NB_I_MAX 8192
.fi
.PP
These constants can be used as the value of the \fBnb\fP argument for integer operations.
.PP
In systems with \fBbig\-endian\fP byte order, the high byte of a number is stored at the
lowest memory address and the low byte at the highest memory address. In a system with
\fBlittle\-endian\fP byte order, on the contrary, the smallest byte is stored at the
smallest address.
.PP
The following diagram shows the placement of the integer depending on the machine
architecture:
.nf
.sp
if( MPU_BYTE_ORDER_BIG_ENDIAN == 0 )
{
[NB-1], . . . , [0];
┌─────────────────────────── . . . ───────────────────────────┐
│ high low │
└─────────────────────────── . . . ───────────────────────────┘
^Sign bit
size: NB.
}
if( MPU_BYTE_ORDER_BIG_ENDIAN == 1 )
{
[0], . . . , [NB-1];
┌─────────────────────────── . . . ───────────────────────────┐
│ high low │
└─────────────────────────── . . . ───────────────────────────┘
^Sign bit
size: NB.
}
.fi
.PP
Here, the symbol \fBNB\fP — denotes the number of bytes of the number.
.PP
To represent integer variables, the user can independently create byte arrays in any
of the following ways:
.nf
.sp
__mpu_byte_t a[NB_I65536];
mpu_int a[NB_I65536];
mpu_int *a = (mpu_int *)malloc( NB_I65536 * sizeof(__mpu_byte_t) );
.fi
.PP
and also use, predefined in \fBlibmpu.h\fP, data types that explicitly talk
about dimensionality:
.nf
.sp
mpu_int4096_t a;
.fi
.PP
Integers can be considered both signed and unsigned. Signed variables are represented in two’s
complement form for convenience of operations with them. Below is a table of some values of an
8\-bit variable in two’s complement form.
.nf
.sp
┌────────────────┬─────────────────┐
│ Decimal │ Binary │
│ representation │ representation │
├────────────────┼─────────────────┤
│ 127 │ 0111 1111 │
│ 3 │ 0000 0011 │
│ 2 │ 0000 0010 │
│ 1 │ 0000 0001 │
│ 0 │ 0000 0000 │
│ -1 │ 1111 1111 │
│ -2 │ 1111 1110 │
│ -3 │ 1111 1101 │
│ -127 │ 1000 0001 │
│ -128 │ 1000 0000 │
└────────────────┴─────────────────┘
.fi
.sp
.SS Real numbers
Real variables, just like integer variables, are stored as byte arrays. The \fBlibmpu.h\fP
header file defines constants that represent the number of bytes for storing real variables:
.nf
.sp
#define NB_R32 4
#define NB_R64 8
#define NB_R128 16
#define NB_R256 32
#define NB_R512 64
#define NB_R1024 128
#define NB_R2048 256
#define NB_R4096 512
#define NB_R8192 1024
#define NB_R16384 2048
#define NB_R32768 4096
#define NB_R65536 8192
#define NB_R_MAX 8192
.fi
.PP
These constants can be used as the value of the \fBnb\fP argument for operations
with real numbers.
.PP
Real numbers have two fields: the shifted exponent and the mantissa. The integer
unit bit is implicit. The sign is located in the high bit of the number.
.PP
The following diagram shows the placement of a real number depending on the
architecture of the machine:
.nf
.sp
if( MPU_BYTE_ORDER_BIG_ENDIAN == 0 )
{
[NB-1], . . . , [nS] │ [nS-1], . . . , [0];
┌────── . . . ───────┬─────────────── . . . ──────────────────┐
│ Sign + Exponent │ Significand │
└────── . . . ───────┴─────────────── . . . ──────────────────┘
^Sign bit ^(1. - implicit)
size: nE nS.
}
if( MPU_BYTE_ORDER_BIG_ENDIAN == 1 )
{
[0], . . . , [nE-1] │ [nE], . . . , [NB-1];
┌────── . . . ───────┬─────────────── . . . ──────────────────┐
│ Sign + Exponent │ Significand │
└────── . . . ───────┴─────────────── . . . ──────────────────┘
^Sign bit ^(1. - implicit)
size: nE nS.
}
.fi
.PP
Here, the symbols \fBnE\fP and \fBnS\fP denote the number of bytes of the exponent and the
number of bytes of the mantissa, respectively.
.PP
The number of bits allocated to represent the sign, exponent and mantissa is distributed
as follows:
.nf
.sp
┌───────────────────────┬───────────────────┬─────────────┐
│ Total number of bits │ (Sign + Exponent) │ Significand │
├───────────────────────┼───────────────────┼─────────────┤
│ 32 │ 1 + 8 + │ 23 │
│ 64 │ 1 + 11 + │ 52 │
│ 128 │ 1 + 31 + │ 96 │
│ 256 │ 1 + 31 + │ 224 │
│ 512 │ 1 + 63 + │ 448 │
│ 1024 │ 1 + 63 + │ 960 │
│ 2048 │ 1 + 127 + │ 1920 │
│ 4096 │ 1 + 127 + │ 3968 │
│ 8192 │ 1 + 255 + │ 7936 │
│ 16384 │ 1 + 255 + │ 16128 │
│ 32768 │ 1 + 511 + │ 32256 │
│ 65536 │ 1 + 511 + │ 65024 │
└───────────────────────┴───────────────────┴─────────────┘
.fi
.PP
The 32\- and 64\-bit number formats are fully consistent with the \fBIEEE\fP (Institute
of Electrical and Electronics Engineers) format.
.PP
For convenience in declaring real\-type variables, the \fBlibmpu.h\fP header file
defines the corresponding data types, the application of which may look, for example,
as follows:
.nf
.sp
mpu_real16384_t a, b;
.fi
.sp
.SS Not\-a\-Numbers
To enhance computational capabilities, the floating\-point number format provides
several special values along with the usual real numbers. These have some meaning
and provide important information about the algorithms and operations in which these
values appear. Special values include real numbers with normalization violations,
indeterminacy, zeros, infinities, and non\-numbers, shown in the following table.
.nf
.sp
┌──────┬───────────────────┬───────────────────┬──────────────────┐
│ Sign │ Exponent │ Significand │ comments │
├──────┼───────────────────┼───────────────────┼──────────────────┤
│ S │ 1111 . . . 1111 │ 0000 . . . 0000 │ +/- inf │
│ S │ 0000 . . . 0000 │ 0000 . . . 0000 │ +/- 0 │
│ 1 │ 1111 . . . 1111 │ 1000 . . . 0000 │ - ind │
│ S │ 1111 . . . 1111 │ 0000 . . . 0001 │ +/- NaN (min) │
│ S │ 1111 . . . 1111 │ 1111 . . . 1111 │ +/- NaN (max) │
└──────┴───────────────────┴───────────────────┴──────────────────┘
Здесь:
+/- inf - +/- infinity;
+/- 0 - +/- signed zero;
- ind - indeterminacy;
+/- NaN (min) - +/- minimal Not-a-Number;
+/- NaN (max) - +/- maximal Not-a-Number.
.fi
.PP
Denormalized numbers:
.nf
.sp
┌──────┬───────────────────┬───────────────────┬──────────────────┐
│ Sign │ Exponent │ Significand │ comments │
├──────┼───────────────────┼───────────────────┼──────────────────┤
│ S │ 0000 . . . 0000 │ 0000 . . . 0001 │ +/- min │
│ S │ 0000 . . . 0000 │ 1111 . . . 1111 │ +/- max │
└──────┴───────────────────┴───────────────────┴──────────────────┘
.fi
.PP
Maximum and minimum real numbers:
.nf
.sp
┌──────┬───────────────────┬───────────────────┬──────────────────┐
│ Sign │ Exponent │ Significand │ comments │
├──────┼───────────────────┼───────────────────┼──────────────────┤
│ S │ 0000 . . . 0001 │ 0000 . . . 0000 │ +/- MIN │
│ S │ 1111 . . . 1110 │ 1111 . . . 1111 │ +/- MAX │
└──────┴───────────────────┴───────────────────┴──────────────────┘
.fi
.sp
.SS Complex numbers
Complex numbers are stored in the machine's memory as a structure consisting
of two real numbers.
.PP
The constants that define the size of complex numbers in bytes are set so
that they represent half the size of the complex number:
.nf
.sp
#define NB_C32 4
#define NB_C64 8
#define NB_C128 16
#define NB_C256 32
#define NB_C512 64
#define NB_C1024 128
#define NB_C2048 256
#define NB_C4096 512
#define NB_C8192 1024
#define NB_C16384 2048
#define NB_C32768 4096
#define NB_C65536 8192
#define NB_C_MAX 8192
.fi
.PP
It is important to note here that functions working with complex variables accept these very
values as a parameter determining the operand size. Thus, for example, to work with a variable
of the \fBmpu_complex256_t\fP type, \fBnb\fP = 32 == \fBNB_C256\fP must be supplied to the
function input, while \fBsizeof\fP(\fBmpu_complex256_t\fP) == 64 == \fBNB_C256\fP * 2.
.PP
The representation of complex numbers in memory is shown in the following diagram:
.nf
.sp
if( MPU_BYTE_ORDER_BIG_ENDIAN == 0 )
{
[NB*2-1], . . . , [NB] │ [NB-1], . . . , [0];
┌──────────── . . . ───────────┬──────────── . . . ───────────┐
│ Real part │ Imaginary │
└──────────── . . . ───────────┴──────────── . . . ───────────┘
size: NB_Real == NB_CXXX NB_Imag == NB_CXXX.
}
if( MPU_BYTE_ORDER_BIG_ENDIAN == 1 )
{
[0], . . . , [NB-1] │ [NB], . . . , [NB*2-1];
┌──────────── . . . ───────────┬──────────── . . . ───────────┐
│ Real part │ Imaginary │
└──────────── . . . ───────────┴──────────── . . . ───────────┘
size: NB_Real == NB_CXXX NB_Imag == NB_CXXX.
}
.fi
.PP
The Imaginary and Real part formats of complex variables are the same as those of real numbers.
.sp
.SH Flags
Most operations on integers and real numbers expose flags. The flags of operations are
placed in an integer 32\-bit variable. The lower 8 bits [7 ... 0] are given for flags
of integer operations. Bits 8 through 15 are occupied by flags set by operations with
real numbers.
.sp
.SS Flags of integer operations:
.nf
.sp
7 6 5 4 3 2 1 0
. . . ─┬────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ V │ R │ Z │ P │ S │ O │ C │ A │
. . . ─┴────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
.sp
A - Auxiliary Carry Flag (carry from lowest 4-bit word)
C - Carry Flag
O - Overflow Flag
S - Sign Flag
P - Parity Flag (of lowest significant byte)
Z - Zero Flag
R - major || remainder
V - Invalid operation
.fi
.PP
NOTE: The \fBA\fP and \fBP\fP flags are exposed only by operations on 8\-bit
and 16\-bit variables.
.sp
.SS Flags of operations with real variables:
.nf
.sp
15 14 13 12 11 10 9 8
. . . ─┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬ . . .
│ INX │ IND │ PLS │ TLS │ UDF │ OVF │ SNG │ DOM │
. . . ─┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴ . . .
.sp
DOM - Domain Flag
SNG - Singularity Flag
OVF - Overflow Flag
UDF - Underflow Flag
TLS - TLOSS Flag
PLS - PLOSS Flag
IND - ind-produsing operation Flag
INX - Inexact Flag
.fi
.PP
The \fBlibmpu.h\fP header file defines flag handling functions such as clearing flags,
resetting, setting, and checking operation flags.
.sp
.SH Exceptions and error codes
Besides flagging operations with integers and real numbers, the \fBLibMPU\fP library supports
the standard \fBerrno\fP variable and, in addition, its own variables \fB__mpu_integer_error_no\fP,
\fB__mpu_real_error_no\fP, \fB__mpu_complex_error_no\fP, \fB__mpu_math_error_no\fP.
.PP
Error codes are defined in the \fBlibmpu.h\fP header file.
.PP
The \fBLibMPU\fP library supports error handling through the \fB__mpu_math_error()\fP function,
which can be overridden by the user at the object code linking stage in the same way that it is
possible to override the \fBmatherr()\fP function when linking programs with a standard \fBC\fP
language library (e.g., \fBGNU Libc\fP).
.PP
In addition, the user can override the \fB__mpu_warning()\fP function, which
can output additional error information.
.PP
As in the case of the \fBmatherr()\fP function of the \fBC\fP standard library,
the parameter of the \fB__mpu_math_error()\fP and \fB__mpu_warning()\fP functions
is a pointer to the \fB__exception\fP structure:
.nf
.sp
struct __exception
{
int who; /* _COMPLEX_, _REAL_, _INTEGER_, _MATH_ */
int type;
__mpu_char8_t *name;
__mpu_char8_t *msg;
int msg_type; /* >= 1 - error, 0 - warning */
int nb_a1; /* number of bytes in arg_1 */
int nb_a2; /* number of bytes in arg_2 */
int nb_rv; /* number of bytes in return_value */
unsigned char *arg_1;
unsigned char *arg_2;
unsigned char *return_value;
};
.fi
.PP
where the error source, error type, the name of the function whose execution caused
the error, as well as pointers to the function arguments and the received return
value are defined.
.PP
Using \fB__mpu_utf8mpu_error()\fP function you can get a pointer to a string constant
containing a text description of the error corresponding to the error code (see
\fB__mpu_integer_error_no\fP, \fB__mpu_real_error_no\fP, \fB__mpu_complex_error_no\fP,
\fB__mpu_math_error_no\fP variables).
.PP
For simple calculations, we usually do not have to override the functions \fBmatherr()\fP,
\fB__mpu_math_error()\fP and \fB__mpu_warning()\fP, but we have kept this possibility as one
of the standard features provided by the \fBC\fP language library.
.sp
.SH SEE ALSO
.BR iadd(3),
.BR isub(3),
.BR iadc(3),
.BR isbb(3),
.BR ishl(3),
.BR ishr(3),
.BR isal(3),
.BR isar(3),
.BR irol(3),
.BR iror(3),
.BR ircl(3),
.BR ircr(3),
.BR ishln(3),
.BR ishrn(3),
.BR isaln(3),
.BR isarn(3),
.BR iroln(3),
.BR irorn(3),
.BR ircln(3),
.BR ircrn(3),
.BR ineg(3),
.BR inot(3),
.BR iand(3),
.BR itest(3),
.BR icmp(3),
.BR ior(3),
.BR ixor(3),
.BR iinc(3),
.BR idec(3),
.BR ixchg(3),
.BR icpy(3),
.BR icvt(3),
.BR imul(3),
.BR ismul(3),
.BR idiv(3),
.BR isdiv(3),
.BR iatoi(3),
.BR iatoui(3),
.BR iitoa(3),
.BR iuitoa(3).
|