.\" 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
Библиотека выполнена как эмулятор процессора с набором регистров и флагов, устанавливаемых
по результатам проведенных операций. Набор целочисленных функций содержит арифметические,
логические операции, а также всевозможные операции сдвига. Для вещественных и комплексных
чисел реализованы основные тригонометрические функции.
.PP
Разрядность ограничена \fB65536\fP бит для арифметических операций и \fB16384\fP бит для
тригонометрии. Ограничения обусловлены порядком рядов аппроксимации.
.SH Форматы данных
Библиотека поддерживает целые, вещественные и комплексные типы. Переменные хранятся
в массивах байтов.
.sp
.SS Целые числа
В заголовочном файле \fBlibmpu.h\fP определены константы, которые представляют количество
байтов для хранения целых переменных:
.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
Данные константы можно использовать в качестве значения аргумента \fBnb\fP для операций
с целыми числами.
.PP
В системах с \fBbig\-endian\fP порядком байтов старший байт числа хранится по наименьшему
адресу памяти, а младший байт — по наибольшему. В системе с \fBlittle\-endian\fP порядком
байтов, напротив, младший байт хранится по наименьшему адресу.
.PP
На следующей схеме представлено размещение целого числа в зависимости от архитектуры
машины:
.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
Здесь, символ \fBNB\fP — обозначает количество байтов числа.
.PP
Для представления целых переменных, пользователь может самостоятельно создавать массивы
байтов любым из перечисленных ниже способов:
.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
а также использовать, предопределенные в \fBlibmpu.h\fP, типы данных, которые прямо
говорят о размерности:
.nf
.sp
mpu_int4096_t a;
.fi
.PP
Целые числа могут рассматриваться как знаковые (\fIsigned\fP), так и беззнаковые (\fIunsigned\fP).
Знаковые переменные, для удобства операций с ними, представляются в дополнительном коде.
Ниже приведена таблица некоторых значений 8\-разрядной переменной в дополнительном коде.
.nf
.sp
┌────────────────┬─────────────────┐
│ Десятичное │ Двоичное │
│ представление │ представление │
├────────────────┼─────────────────┤
│ 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 Вещественные числа
Вещественные переменные, также как и целые, хранятся в виде массивов байтов.
В заголовочном файле \fBlibmpu.h\fP определены константы, которые представляют
количество байтов для хранения вещественных переменных:
.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
Данные константы можно использовать в качестве значения аргумента \fBnb\fP для
операций с вещественными числами.
.PP
Вещественные числа имеют в своем составе два поля: смещенной экспоненты и мантиссы.
Бит целой единицы неявный. Знак расположен в старшем бите числа.
.PP
На следующей схеме представлено размещение вещественного числа в зависимости
от архитектуры машины:
.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
Здесь, символы \fBnE\fP и \fBnS\fP — обозначают количество байтов экспоненты и количество
байтов мантиссы, соответственно.
.PP
Количество бит выделяемое для представления знака, экспоненты и мантиссы распределено
следующим образом:
.nf
.sp
┌───────────────────────┬───────────────────┬─────────────┐
│ Общее количество бит │ (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
Форматы 32\- и 64\-битных чисел полностью совпадают с \fBIEEE\fP (Institute of Electrical
and Electronics Engineers) форматом.
.PP
Для удобства декларирования переменных вещественного типа в заголовочном файле
\fBlibmpu.h\fP определены соответствующие типы данных, применение которых может
выглядеть, например, следующим образом:
.nf
.sp
mpu_real16384_t a, b;
.fi
.sp
.SS Не числа
Для расширения вычислительных возможностей в формате чисел с плавающей точкой наряду
с обычными вещественными числами предусмотрено несколько специальных значений. Они
имеют определенный смысл и дают важную информацию об алгоритмах и операциях, в которых
появляются эти значения. К специальным значениям относятся вещественные числа
с нарушением нормализации, неопределенность, нули, бесконечности и не числа,
представленные в следующей таблице.
.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 - +/- бесконечность;
+/- 0 - +/- знаковый нуль;
- ind - неопределенность;
+/- NaN (min) - +/- минимальное не число;
+/- NaN (max) - +/- максимальное не число.
.fi
.PP
Числа с нарушением нормализации:
.nf
.sp
┌──────┬───────────────────┬───────────────────┬──────────────────┐
│ Sign │ Exponent │ Significand │ comments │
├──────┼───────────────────┼───────────────────┼──────────────────┤
│ S │ 0000 . . . 0000 │ 0000 . . . 0001 │ +/- min │
│ S │ 0000 . . . 0000 │ 1111 . . . 1111 │ +/- max │
└──────┴───────────────────┴───────────────────┴──────────────────┘
.fi
.PP
Кодировка максимального и минимального вещественных чисел:
.nf
.sp
┌──────┬───────────────────┬───────────────────┬──────────────────┐
│ Sign │ Exponent │ Significand │ comments │
├──────┼───────────────────┼───────────────────┼──────────────────┤
│ S │ 0000 . . . 0001 │ 0000 . . . 0000 │ +/- MIN │
│ S │ 1111 . . . 1110 │ 1111 . . . 1111 │ +/- MAX │
└──────┴───────────────────┴───────────────────┴──────────────────┘
.fi
.sp
.SS Комплексные числа
Комплексные числа хранятся в памяти машины как структура, состоящая из двух
вещественных чисел.
.PP
Константы, определяющие размер комплексных чисел в байтах, заданы так, что
они представляют половину размера комплексного числа:
.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
Здесь важно отметить, что функции, работающие с комплексными переменными в качестве параметра,
определяющего размер операндов принимают именно эти величины. Например для работы
с переменной типа \fBmpu_complex256_t\fP, на вход функций надо подавать \fBnb\fP = 32 ==
\fBNB_C256\fP, в то время, как \fBsizeof\fP(\fBmpu_complex256_t\fP) == 64 == \fBNB_C256\fP * 2.
.PP
Представление комплексных чисел в памяти показано на следующей схеме:
.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
Форматы вещественной и мнимой частей комплексных переменных совпадают с форматами вещественных чисел.
.sp
.SH Флаги
Большинство операций с целыми и вещественными числами выставляют флаги. Флаги операций
размещены в целой 32\-битной переменной. Младшие 8 битов [7 ... 0] отданы под флаги
целочисленных операций. Биты с 8\-го по 15\-й занимают флаги, выставляемые операциями
с вещественными числами.
.sp
.SS Флаги целочисленных операций:
.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: Флаги \fBA\fP и \fBP\fP выставляются только операциями над 8\-разрядными
и 16\-разрядными переменными.
.sp
.SS Флаги операций с вещественными переменными:
.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
В заголовочном файле \fBlibmpu.h\fP определены функции работы с флагами, такие как
очистка флагов, сброс, выставление флагов, а также проверки флагов операций.
.sp
.SH Исключения и коды ошибок
Помимо выставления флагов операциями с целыми и вещественными числами, библиотека \fBLibMPU\fP
поддерживает стандартную переменную \fBerrno\fP и, ктоме того, собственные переменные
\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
Коды ошибок определены в заголовочном файле \fBlibmpu.h\fP.
.PP
Библиотека \fBLibMPU\fP поддерживает обработку ошибок посредством функции
\fB__mpu_math_error()\fP, которая может быть переопределена пользователем
на этапе компоновки объектного кода так, как это возможно при переопределении
функции \fBmatherr()\fP во время компоновки программ со стандартной библиотекой языка \fBC\fP
(например, \fBGNU Libc\fP).
.PP
Кроме того, пользователь может переопределить функцию \fB__mpu_warning()\fP,
которая выводит дополнительную информацию об ошибках.
.PP
Как и в случае функции \fBmatherr()\fP стандартной библиотеки языка \fBC\fP,
параметром функций \fB__mpu_math_error()\fP, \fB__mpu_warning()\fP является
указатель на структуру \fB__exception\fP:
.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
в которой определены: источник ошибки, тип ошибки, имя функции выполнение которой
привело к ошибке, а также указатели на аргументы функции и полученное возвращаемое
значение.
.PP
С помощью функции \fB__mpu_utf8mpu_error()\fP можно получить указатель на строковую
константу, содержащую текстовое описание ошибки, соответствующее коду ошибки (см.
переменные \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
Для простых вычислений, как правило, не приходится переопределять функции
\fBmatherr()\fP, \fB__mpu_math_error()\fP и \fB__mpu_warning()\fP, однако
мы сохранили такую возможность как одну из стандартных возможностей,
предоставляемых библиотекой языка \fBC\fP.
.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).