Библиотека complex — API-документация
Пакет TMC Suite. Статическая библиотека процедурной (Си-стиль) арифметики комплексных чисел. Язык документации: русский. Все сигнатуры приведены по исходнику
src/libs/complex/CMPLXALL.CPPи общим заголовкамsrc/Include/COMPLEX1.H,src/Include/Typedef.h.
1. Назначение библиотеки
complex — статическая библиотека (StaticLibrary, собирается под win32 и x64), реализующая процедурную арифметику комплексных чисел в стиле языка Си. Все операции оформлены как обычные функции, принимающие и возвращающие значения-структуры _complex (без перегрузки операторов и без классов C++).
Библиотека предоставляет:
- доступ к компонентам комплексного числа (действительная/мнимая часть), сопряжение, унарный минус;
- базовую арифметику: сложение, вычитание, умножение, деление, возведение в степень, сравнение;
- модуль числа (с защитой от переполнения), фазу/аргумент (в разных диапазонах), квадратный корень;
- элементарные функции комплексного переменного: экспонента, натуральный логарифм, синус, косинус, гиперболические синус и косинус;
- вспомогательные величины (сумма и разность квадратов компонент).
Библиотека complex.lib используется вьюверами TMC Suite и (транзитивно, через вьюверы и заголовки) счётными ядрами при работе с матрицами рассеяния (S-матрицами) и расчётом полей.
2. Состав сборки
В проект complex.vcxproj (StaticLibrary, toolset v145 — Visual Studio 2022, платформы Win32 и x64) входит единственный исходный файл:
| Файл | Назначение |
|---|---|
CMPLXALL.CPP |
Полная реализация всех функций библиотеки комплексной арифметики |
Legacy-файлы вне сборки (не документируются)
В каталоге src/libs/complex/ присутствуют файлы старых систем сборки, которые не используются актуальным проектом complex.vcxproj и в данной документации не описываются:
complex.dsp,complex.dsw— проект/рабочее пространство Visual C++ 6.0;complex.vcproj(и.7.00.old,*.user) — проект Visual Studio 2003/2005;COMPLEX.SLN,COMPLEX.sln.old,*.suo,*.ncb,*.opt,*.plg,UpgradeLog.XML— служебные файлы IDE.
3. Типы данных
3.1. _complex — комплексное число
Прототипы всех функций объявлены в COMPLEX1.H и оперируют типом _complex — структурой с двумя вещественными полями:
| Поле | Тип | Смысл |
|---|---|---|
x |
_real |
Действительная часть |
y |
_real |
Мнимая часть |
Определение типа зависит от языка трансляции (см. Typedef.h):
- Для C (
#ifndef __cplusplus) определяется собственная структура:
typedef struct tag_complex {
_real x; // действительная часть
_real y; // мнимая часть
} _complex;
- Для C++ (а
CMPLXALL.CPPтранслируется именно как C++)Typedef.hсобственную структуру не объявляет, а подключает<math.h>. В этом случае используется встроенная в CRT компилятора MSVC структураstruct _complexиз<math.h>с полямиdouble x, y. Доступ к компонентам во всех функциях выполняется единообразно —z.x(действительная часть) иz.y(мнимая часть).
3.2. _real — вещественный тип
_real (определён в Typedef.h) — это псевдоним float либо double в зависимости от макроса _HIGH_ACCURACY:
| Состояние макроса | _real |
Хранение |
|---|---|---|
_HIGH_ACCURACY определён (по умолчанию) |
double |
8 байт |
_HIGH_ACCURACY не определён |
float |
4 байта |
По умолчанию Typedef.h определяет _HIGH_ACCURACY, поэтому _real = double.
Возможное несоответствие точности. Если
_realопределён какfloat, а в C++-сборке_complexберётся из CRT<math.h>с полямиdouble x, y, типы компонент структуры и_realрасходятся. В исходном коде присутствуют явные приведения к(_real)(например, вaimag,ctof, тригонометрических функциях), которые частично сглаживают это расхождение, но оно может приводить к потере точности или предупреждениям компилятора.
3.3. Закомментированный класс C++ (_complex.hpp)
В src/Include/ есть файл _complex.hpp, содержащий объектно-ориентированную (C++-класс) реализацию комплексных чисел. Он полностью закомментирован и не используется актуальной сборкой. В данной документации не описывается.
4. Публичные функции
О макросах
_far,_fortranи пр. В сигнатурах оригинального заголовка функции снабжены атрибутами_farи_fortran(например,_real _far _fortran aimag( _complex )). Это остатки моделей памяти и соглашений о вызове 16/32-битного кода. ВTypedef.hвсе они (_far,_near,_huge,_fortran,_pascal,_cdecl) определены как пустые макросы и на современных платформах никакого эффекта не дают. Для краткости ниже в сигнатурах они опущены — приводится «чистый» прототип. Полные прототипы см. вCOMPLEX1.H.
4.1. Доступ к компонентам и сопряжение
_real aimag(_complex z)
Возвращает мнимую часть комплексного числа.
- Параметры:
z(_complex) — число. - Возврат:
z.y(_real) — мнимая часть.
_real ctof(_complex z)
Возвращает действительную часть комплексного числа («complex (real component) to float conversion»).
- Параметры:
z(_complex) — число. - Возврат:
z.x(_real) — действительная часть.
_complex ftoc(_real, _real)
Должна собирать комплексное число из двух вещественных значений (действительная и мнимая части).
- Параметры: первый
_real— действительная часть, второй_real— мнимая часть. - Возврат:
_complex— собранное число. - Важно: прототип объявлен в
COMPLEX1.H, однако реализация вCMPLXALL.CPPотсутствует — найден только закомментированный inline-вариант под макросомINLN_COMPLEXв заголовке. При линковке безINLN_COMPLEXобращение кftocприведёт к ошибке неразрешённого символа.
_complex conjg(_complex z)
Комплексное сопряжение: меняет знак мнимой части.
- Параметры:
z(_complex) — число. - Возврат:
_complexсо значением(z.x, −z.y).
_complex cneg(_complex z)
Унарный минус: меняет знак обеих компонент.
- Параметры:
z(_complex) — число. - Возврат:
_complexсо значением(−z.x, −z.y).
Макросы itocx(i, j) и ltocx(i, j) (COMPLEX1.H)
Преобразование целочисленных значений в комплексное число через ftoc:
#define itocx( i, j ) ftoc((_real)i, (_real)j)
#define ltocx( i, j ) ftoc((_real)i, (_real)j)
itocx(i, j)— из парыint(действительнаяi, мнимаяj);ltocx(i, j)— из парыlong(действительнаяi, мнимаяj).
Оба макроса опираются на ftoc (см. замечание о её реализации выше).
4.2. Арифметика
_complex cadd(_complex l, _complex r)
Сумма двух комплексных чисел.
- Параметры:
l,r(_complex) — слагаемые. - Возврат:
_complexсо значением(l.x + r.x, l.y + r.y).
_complex csub(_complex l, _complex r)
Разность двух комплексных чисел.
- Параметры:
l,r(_complex) — уменьшаемое и вычитаемое. - Возврат:
_complexсо значением(l.x − r.x, l.y − r.y).
_complex cmul(_complex l, _complex r)
Произведение двух комплексных чисел.
- Параметры:
l,r(_complex) — сомножители. - Возврат:
_complexсо значением(l.x·r.x − l.y·r.y, l.x·r.y + l.y·r.x).
_complex cdiv(_complex l, _complex r)
Частное двух комплексных чисел l / r.
- Параметры:
l(_complex) — делимое;r(_complex) — делитель. - Возврат:
_complex— частное. - Защита от деления на ноль: если
r == (0, 0): - при
l == (0, 0)возвращается(0, 0); - иначе возвращается
(REAL_MAX/√2, REAL_MAX/√2)(предельно большое значение как индикатор переполнения). - Формула (при
r ≠ 0,den = r.x² + r.y²):x = (l.x·r.x + l.y·r.y)/den,y = (r.x·l.y − l.x·r.y)/den.
_complex cpow(_complex l, _complex r)
Возведение комплексного числа в комплексную степень: l^r.
- Параметры:
l(_complex) — основание;r(_complex) — показатель. - Возврат:
_complex— результат, вычисляемый какcexp(cmul(r, clog(l))). - Особый случай: при
l == (0, 0)возвращаетсяl(то есть(0, 0)); результат в этом случае математически не определён.
_complex cpowf(_complex l, _real r)
Возведение комплексного числа в вещественную степень: l^r.
- Параметры:
l(_complex) — основание;r(_real) — вещественный показатель. - Возврат:
_complex— результат. - Особый случай: при
l == (0, 0)возвращаетсяl; результат не определён. - Важно: в реализации присутствует особенность исходного кода (см. раздел 7) — логарифм берётся от неинициализированной переменной, а не от основания
l.
int ceq(_complex l, _complex r)
Проверка равенства двух комплексных чисел.
- Параметры:
l,r(_complex) — сравниваемые числа. - Возврат:
1, еслиl.x == r.xиl.y == r.y(поэлементное равенство); иначе0.
4.3. Модуль, фаза, корень, элементарные функции
_real arg_cpx(_complex z)
Аргумент (угол) комплексного числа в радианах, вычисляемый через арксинус: asin(z.y / cabsv(z)).
- Параметры:
z(_complex) — число. - Возврат:
_real— угол в радианах. Диапазон значенийasin—[−π/2, π/2].
_real cphase(_complex z)
Угол (фаза) комплексного числа в радианах, определяемый по квадрантам и приведённый к диапазону 0 … −2π.
- Параметры:
z(_complex) — число. - Возврат:
_real— угол в радианах. - Особые случаи:
z == (0, 0)→0;z.x == 0,z.y > 0→−1.5·π;z.x == 0,z.y < 0→−0.5·π;z.y == 0,z.x > 0→0;z.y == 0,z.x < 0→−π;- в остальных случаях за основу берётся
atan(z.y/z.x)с поправками по знакамz.x,z.y(вычитание2πилиπ).
_real cabsv(_complex z)
Модуль (абсолютная величина) комплексного числа с защитой от переполнения за счёт масштабирования.
- Параметры:
z(_complex) — число. - Возврат:
_real— модульm·√((z.x/m)² + (z.y/m)²), гдеm = max(|z.x|, |z.y|). Приm == 0возвращается0. - Назначение масштаба
m: позволяет вычислять модуль чисел с очень большими компонентами без промежуточного переполнения.
_real cabsm(_complex z)
Квадратный корень из разности квадратов компонент с масштабированием. Не является обычным модулем.
- Параметры:
z(_complex) — число. - Возврат:
_real—m·√((z.x/m)² − (z.y/m)²), гдеm = max(|z.x|, |z.y|). Приm == 0возвращается0. - Внимание: под корнем стоит разность (а не сумма), поэтому результат — не модуль; при
|z.y| > |z.x|подкоренное выражение отрицательно.
_real csqsum(_complex z)
Сумма квадратов компонент.
- Параметры:
z(_complex) — число. - Возврат:
_real—z.x² + z.y²(квадрат модуля без извлечения корня).
_real csqsub(_complex z)
Масштабированная разность квадратов компонент.
- Параметры:
z(_complex) — число. - Возврат:
_real—m²·((z.x/m)² − (z.y/m)²), гдеm = max(|z.x|, |z.y|). Приm == 0возвращается0. Математически равноz.x² − z.y², но вычисляется через масштабирование для устойчивости.
_complex csqrt(_complex z)
Положительное значение квадратного корня из комплексного числа.
- Параметры:
z(_complex) — число. - Возврат:
_complex— корень. Модуль результата —√cabsv(z), аргумент —arg_cpx(z)/2; результат(√m·cos(θ/2), √m·sin(θ/2)).
_complex clog(_complex z)
Натуральный логарифм комплексного числа.
- Параметры:
z(_complex) — число. - Возврат:
_complex—(ln(cabsv(z)), arg_cpx(z)): действительная часть — логарифм модуля, мнимая часть — аргумент (черезarg_cpx).
_complex cexp(_complex z)
Комплексная экспонента e^z.
- Параметры:
z(_complex) — число. - Возврат:
_complex—(e^{z.x}·cos(z.y), e^{z.x}·sin(z.y)). - Оптимизации: при
z.x == 0множитель экспоненты равен1; приz.y == 0результат — чисто вещественное числоe^{z.x}.
_complex csin(_complex z)
Синус комплексного числа.
- Параметры:
z(_complex) — число. - Возврат:
_complex—(sin(z.x)·cosh(z.y), cos(z.x)·sinh(z.y)).
_complex ccos(_complex z)
Косинус комплексного числа.
- Параметры:
z(_complex) — число. - Возврат:
_complex—(cos(z.x)·cosh(z.y), −sin(z.x)·sinh(z.y)).
_complex csinh(_complex z)
Гиперболический синус комплексного числа.
- Параметры:
z(_complex) — число. - Возврат:
_complex—(sinh(z.x)·cos(z.y), cosh(z.x)·sin(z.y)).
_complex ccosh(_complex z)
Гиперболический косинус комплексного числа.
- Параметры:
z(_complex) — число. - Возврат:
_complex—(cos(z.y)·cosh(z.x), sin(z.y)·sinh(z.x)).
5. Макросы и константы
5.1. Управляющие макросы (Typedef.h)
| Макрос | Назначение |
|---|---|
_HIGH_ACCURACY |
Если определён (по умолчанию) — _real = double; иначе float |
_far, _near, _huge |
Пустые макросы — остатки моделей памяти near/far/huge (win16/DOS). Эффекта на современных платформах нет |
_fortran, _pascal, _cdecl |
Пустые макросы — остатки соглашений о вызове (Fortran/Pascal/cdecl). Эффекта нет |
5.2. Управляющий макрос INLN_COMPLEX (COMPLEX1.H)
Если макрос INLN_COMPLEX определён, функции aimag, ctof, ftoc, conjg, cneg заменяются inline-макросами (раскрываются в код, использующий общую переменную _complex z). Если не определён (по умолчанию) — используются обычные функции из CMPLXALL.CPP.
#ifdef INLN_COMPLEX
#define aimag(z) ( z.y )
#define ctof(z) ( z.x )
#define ftoc(r,i) (( z.x = r, z.y = i ), z)
#define conjg(z) (( z.y = -z.y ), z)
#define cneg(z) ( ( z.x = -z.x, z.y = -z.y ), z)
#else
/* объявления функций */
#endif
Внимание: в ветке
INLN_COMPLEXименно макросftocдаёт единственную (inline) реализациюftoc. БезINLN_COMPLEXфункцияftocне определена ни как функция, ни как макрос (см. раздел 7).
5.3. Пределы точности типа _real (Typedef.h, из <float.h>)
Значения зависят от того, float или double стоит за _real:
| Макрос | _real = double |
_real = float |
Смысл |
|---|---|---|---|
REAL_MAX |
DBL_MAX |
FLT_MAX |
Максимальное представимое значение |
REAL_MIN |
DBL_MIN |
FLT_MIN |
Минимальное положительное значение |
REAL_DIG |
DBL_DIG |
FLT_DIG |
Число значащих десятичных цифр |
REAL_EPSILON |
DBL_EPSILON |
FLT_EPSILON |
Машинный эпсилон |
REAL_MAX_10_EXP |
DBL_MAX_10_EXP |
FLT_MAX_10_EXP |
Максимальный десятичный порядок |
REAL_MIN_10_EXP |
DBL_MIN_10_EXP |
FLT_MIN_10_EXP |
Минимальный десятичный порядок |
REAL_MAX напрямую используется в cdiv как индикатор переполнения при делении на ноль.
5.4. Математические и физические константы (Typedef.h)
| Константа | Значение | Смысл |
|---|---|---|
PI |
(_real)3.141592653589793 |
Число π |
MU_NUL |
(_real)12.56637e-7 |
Магнитная постоянная μ₀ (Гн/м) |
EPSILON_NUL |
(_real)8.85418757e-12 |
Электрическая постоянная ε₀ (Ф/м) |
LIGHT_VEL |
(_real)2.99792458e8 |
Скорость света в вакууме (м/с) |
6. Зависимости
Системные заголовки: <stdlib.h>, <math.h>.
Общие заголовки проекта (src/Include/): typedef.h (типы _real, _complex, константы), complex1.h (прототипы функций, макросы itocx/ltocx/INLN_COMPLEX).
Библиотеки TMC Suite: библиотека complex не зависит от других библиотек проекта.
Обратные зависимости: complex.lib — зависимость вьюверов (Tmcgrout, DiaNapGr, Tmcrtout) и, транзитивно, счётных ядер при работе с S-матрицами, диаграммами направленностей и полями.
7. Замечания по реализации
Ниже перечислены особенности исходного кода CMPLXALL.CPP, подтверждённые прямым чтением файла. Они приведены нейтрально, как факты об исходном коде. Это научный код — здесь они не исправляются, а только фиксируются; решение об исправлении за автором.
7.1. cpowf — логарифм неинициализированной переменной
В функции cpowf (строка ~212 файла CMPLXALL.CPP) логарифм берётся от локальной переменной z, которая на этот момент не инициализирована, вместо основания l:
_complex _far _fortran cpowf( _complex l, _real r )
{
_complex z;
if( l.x == (_real)0 && l.y == (_real)0 )
return( l );
z = clog( z ); // <-- использует неинициализированную z; ожидалось clog( l )
z.x = r*z.x;
z.y = r*z.y;
return( cexp(z) );
}
По аналогии с cpow (где используется clog(l)) и по смыслу операции l^r здесь, по-видимому, должно быть z = clog( l ). В текущем виде результат cpowf зависит от мусора в неинициализированной памяти и не соответствует математической операции. Не исправлено (научный код).
7.2. Отсутствие реализации ftoc
Функция ftoc объявлена в COMPLEX1.H (в ветке без INLN_COMPLEX), но её реализация в CMPLXALL.CPP отсутствует. Единственный «работающий» вариант — inline-макрос ftoc(r,i) в ветке INLN_COMPLEX. Поскольку макросы itocx/ltocx раскрываются в вызов ftoc, при сборке без INLN_COMPLEX любое их использование (как и прямой вызов ftoc) приведёт к ошибке линковки «неразрешённый внешний символ».
The complex library — API documentation
TMC Suite package. A static library of procedural (C-style) complex-number arithmetic. All signatures are taken from the source
src/libs/complex/CMPLXALL.CPPand the shared headerssrc/Include/COMPLEX1.H,src/Include/Typedef.h.
1. Purpose of the library
complex is a static library (StaticLibrary, built for win32 and x64) that
implements procedural complex-number arithmetic in C style. All operations are
written as ordinary functions that take and return _complex structure values
(without operator overloading and without C++ classes).
The library provides:
- access to the components of a complex number (real/imaginary part), conjugation, unary minus;
- basic arithmetic: addition, subtraction, multiplication, division, exponentiation, comparison;
- the magnitude of a number (with overflow protection), the phase/argument (in different ranges), the square root;
- elementary functions of a complex variable: exponential, natural logarithm, sine, cosine, hyperbolic sine and cosine;
- auxiliary quantities (the sum and difference of the squares of the components).
The complex.lib library is used by the viewers of TMC Suite and (transitively,
through the viewers and headers) by the compute kernels when working with
scattering matrices (S-matrices) and field computation.
2. Build composition
The complex.vcxproj project (StaticLibrary, toolset v145 — Visual Studio
2022, platforms Win32 and x64) contains a single source file:
| File | Purpose |
|---|---|
CMPLXALL.CPP |
The complete implementation of all functions of the complex-arithmetic library |
Legacy files outside the build (not documented)
The src/libs/complex/ directory contains files of old build systems that are
not used by the current complex.vcxproj project and are not described in
this documentation:
complex.dsp,complex.dsw— the Visual C++ 6.0 project/workspace;complex.vcproj(and.7.00.old,*.user) — the Visual Studio 2003/2005 project;COMPLEX.SLN,COMPLEX.sln.old,*.suo,*.ncb,*.opt,*.plg,UpgradeLog.XML— IDE service files.
3. Data types
3.1. _complex — a complex number
The prototypes of all functions are declared in COMPLEX1.H and operate on the
_complex type — a structure with two real fields:
| Field | Type | Meaning |
|---|---|---|
x |
_real |
The real part |
y |
_real |
The imaginary part |
The type definition depends on the translation language (see Typedef.h):
- For C (
#ifndef __cplusplus) its own structure is defined:
typedef struct tag_complex {
_real x; // real part
_real y; // imaginary part
} _complex;
- For C++ (and
CMPLXALL.CPPis translated exactly as C++),Typedef.hdoes not declare its own structure but includes<math.h>. In that case thestruct _complexbuilt into the MSVC compiler's CRT from<math.h>with fieldsdouble x, yis used. Access to the components in all functions is done uniformly —z.x(the real part) andz.y(the imaginary part).
3.2. _real — the real type
_real (defined in Typedef.h) is an alias for float or double depending on
the _HIGH_ACCURACY macro:
| Macro state | _real |
Storage |
|---|---|---|
_HIGH_ACCURACY defined (by default) |
double |
8 bytes |
_HIGH_ACCURACY not defined |
float |
4 bytes |
By default Typedef.h defines _HIGH_ACCURACY, so _real = double.
Possible precision mismatch. If
_realis defined asfloat, while in the C++ build_complexis taken from the CRT<math.h>with fieldsdouble x, y, the types of the structure components and_realdiverge. The source code contains explicit casts to(_real)(for example, inaimag,ctof, the trigonometric functions) that partially smooth this discrepancy, but it may lead to a loss of precision or to compiler warnings.
3.3. The commented-out C++ class (_complex.hpp)
src/Include/ contains a file _complex.hpp with an object-oriented (C++-class)
implementation of complex numbers. It is fully commented out and not used by
the current build. It is not described in this documentation.
4. Public functions
About the
_far,_fortranand similar macros. In the signatures of the original header the functions are decorated with the_farand_fortranattributes (for example,_real _far _fortran aimag( _complex )). These are remnants of the memory models and calling conventions of 16/32-bit code. InTypedef.hall of them (_far,_near,_huge,_fortran,_pascal,_cdecl) are defined as empty macros and have no effect on modern platforms. For brevity they are omitted from the signatures below — a "clean" prototype is given. SeeCOMPLEX1.Hfor the full prototypes.
4.1. Component access and conjugation
_real aimag(_complex z)
Returns the imaginary part of a complex number.
- Parameters:
z(_complex) — the number. - Return:
z.y(_real) — the imaginary part.
_real ctof(_complex z)
Returns the real part of a complex number ("complex (real component) to float conversion").
- Parameters:
z(_complex) — the number. - Return:
z.x(_real) — the real part.
_complex ftoc(_real, _real)
Should assemble a complex number from two real values (the real and imaginary parts).
- Parameters: the first
_real— the real part, the second_real— the imaginary part. - Return:
_complex— the assembled number. - Important: the prototype is declared in
COMPLEX1.H, but the implementation is absent fromCMPLXALL.CPP— only a commented-out inline variant under theINLN_COMPLEXmacro is found in the header. When linking withoutINLN_COMPLEX, a reference toftocwill cause an unresolved-symbol error.
_complex conjg(_complex z)
Complex conjugation: changes the sign of the imaginary part.
- Parameters:
z(_complex) — the number. - Return:
_complexwith the value(z.x, −z.y).
_complex cneg(_complex z)
Unary minus: changes the sign of both components.
- Parameters:
z(_complex) — the number. - Return:
_complexwith the value(−z.x, −z.y).
The macros itocx(i, j) and ltocx(i, j) (COMPLEX1.H)
Conversion of integer values into a complex number via ftoc:
#define itocx( i, j ) ftoc((_real)i, (_real)j)
#define ltocx( i, j ) ftoc((_real)i, (_real)j)
itocx(i, j)— from a pair ofint(reali, imaginaryj);ltocx(i, j)— from a pair oflong(reali, imaginaryj).
Both macros rely on ftoc (see the note about its implementation above).
4.2. Arithmetic
_complex cadd(_complex l, _complex r)
The sum of two complex numbers.
- Parameters:
l,r(_complex) — the addends. - Return:
_complexwith the value(l.x + r.x, l.y + r.y).
_complex csub(_complex l, _complex r)
The difference of two complex numbers.
- Parameters:
l,r(_complex) — the minuend and subtrahend. - Return:
_complexwith the value(l.x − r.x, l.y − r.y).
_complex cmul(_complex l, _complex r)
The product of two complex numbers.
- Parameters:
l,r(_complex) — the factors. - Return:
_complexwith the value(l.x·r.x − l.y·r.y, l.x·r.y + l.y·r.x).
_complex cdiv(_complex l, _complex r)
The quotient of two complex numbers l / r.
- Parameters:
l(_complex) — the dividend;r(_complex) — the divisor. - Return:
_complex— the quotient. - Division-by-zero protection: if
r == (0, 0): - when
l == (0, 0),(0, 0)is returned; - otherwise
(REAL_MAX/√2, REAL_MAX/√2)is returned (an extremely large value as an overflow indicator). - Formula (when
r ≠ 0,den = r.x² + r.y²):x = (l.x·r.x + l.y·r.y)/den,y = (r.x·l.y − l.x·r.y)/den.
_complex cpow(_complex l, _complex r)
Raising a complex number to a complex power: l^r.
- Parameters:
l(_complex) — the base;r(_complex) — the exponent. - Return:
_complex— the result, computed ascexp(cmul(r, clog(l))). - Special case: when
l == (0, 0),lis returned (that is,(0, 0)); the result in this case is mathematically undefined.
_complex cpowf(_complex l, _real r)
Raising a complex number to a real power: l^r.
- Parameters:
l(_complex) — the base;r(_real) — the real exponent. - Return:
_complex— the result. - Special case: when
l == (0, 0),lis returned; the result is undefined. - Important: the implementation contains a source-code peculiarity (see section
7) — the logarithm is taken of an uninitialized variable, not of the base
l.
int ceq(_complex l, _complex r)
Checks the equality of two complex numbers.
- Parameters:
l,r(_complex) — the numbers being compared. - Return:
1ifl.x == r.xandl.y == r.y(component-wise equality); otherwise0.
4.3. Magnitude, phase, root, elementary functions
_real arg_cpx(_complex z)
The argument (angle) of a complex number in radians, computed via arcsine:
asin(z.y / cabsv(z)).
- Parameters:
z(_complex) — the number. - Return:
_real— the angle in radians. The range ofasinis[−π/2, π/2].
_real cphase(_complex z)
The angle (phase) of a complex number in radians, determined by quadrant and
reduced to the range 0 … −2π.
- Parameters:
z(_complex) — the number. - Return:
_real— the angle in radians. - Special cases:
z == (0, 0)→0;z.x == 0,z.y > 0→−1.5·π;z.x == 0,z.y < 0→−0.5·π;z.y == 0,z.x > 0→0;z.y == 0,z.x < 0→−π;- in the other cases
atan(z.y/z.x)is used as the base, with corrections by the signs ofz.x,z.y(subtracting2πorπ).
_real cabsv(_complex z)
The magnitude (absolute value) of a complex number, with overflow protection via scaling.
- Parameters:
z(_complex) — the number. - Return:
_real— the magnitudem·√((z.x/m)² + (z.y/m)²), wherem = max(|z.x|, |z.y|). Whenm == 0,0is returned. - Purpose of the scale
m: it allows the magnitude of numbers with very large components to be computed without intermediate overflow.
_real cabsm(_complex z)
The square root of the difference of the squares of the components, with scaling. It is not an ordinary magnitude.
- Parameters:
z(_complex) — the number. - Return:
_real—m·√((z.x/m)² − (z.y/m)²), wherem = max(|z.x|, |z.y|). Whenm == 0,0is returned. - Note: the difference (not the sum) is under the root, so the result is not
a magnitude; when
|z.y| > |z.x|, the radicand is negative.
_real csqsum(_complex z)
The sum of the squares of the components.
- Parameters:
z(_complex) — the number. - Return:
_real—z.x² + z.y²(the squared magnitude, without taking the root).
_real csqsub(_complex z)
The scaled difference of the squares of the components.
- Parameters:
z(_complex) — the number. - Return:
_real—m²·((z.x/m)² − (z.y/m)²), wherem = max(|z.x|, |z.y|). Whenm == 0,0is returned. Mathematically equal toz.x² − z.y², but computed via scaling for stability.
_complex csqrt(_complex z)
The positive value of the square root of a complex number.
- Parameters:
z(_complex) — the number. - Return:
_complex— the root. The magnitude of the result is√cabsv(z), the argument isarg_cpx(z)/2; the result is(√m·cos(θ/2), √m·sin(θ/2)).
_complex clog(_complex z)
The natural logarithm of a complex number.
- Parameters:
z(_complex) — the number. - Return:
_complex—(ln(cabsv(z)), arg_cpx(z)): the real part is the logarithm of the magnitude, the imaginary part is the argument (viaarg_cpx).
_complex cexp(_complex z)
The complex exponential e^z.
- Parameters:
z(_complex) — the number. - Return:
_complex—(e^{z.x}·cos(z.y), e^{z.x}·sin(z.y)). - Optimizations: when
z.x == 0the exponential factor equals1; whenz.y == 0the result is a purely real numbere^{z.x}.
_complex csin(_complex z)
The sine of a complex number.
- Parameters:
z(_complex) — the number. - Return:
_complex—(sin(z.x)·cosh(z.y), cos(z.x)·sinh(z.y)).
_complex ccos(_complex z)
The cosine of a complex number.
- Parameters:
z(_complex) — the number. - Return:
_complex—(cos(z.x)·cosh(z.y), −sin(z.x)·sinh(z.y)).
_complex csinh(_complex z)
The hyperbolic sine of a complex number.
- Parameters:
z(_complex) — the number. - Return:
_complex—(sinh(z.x)·cos(z.y), cosh(z.x)·sin(z.y)).
_complex ccosh(_complex z)
The hyperbolic cosine of a complex number.
- Parameters:
z(_complex) — the number. - Return:
_complex—(cos(z.y)·cosh(z.x), sin(z.y)·sinh(z.x)).
5. Macros and constants
5.1. Control macros (Typedef.h)
| Macro | Purpose |
|---|---|
_HIGH_ACCURACY |
If defined (by default) — _real = double; otherwise float |
_far, _near, _huge |
Empty macros — remnants of the near/far/huge memory models (win16/DOS). No effect on modern platforms |
_fortran, _pascal, _cdecl |
Empty macros — remnants of calling conventions (Fortran/Pascal/cdecl). No effect |
5.2. The INLN_COMPLEX control macro (COMPLEX1.H)
If the INLN_COMPLEX macro is defined, the functions aimag, ctof, ftoc,
conjg, cneg are replaced with inline macros (expanded into code that uses a
common variable _complex z). If it is not defined (by default), the ordinary
functions from CMPLXALL.CPP are used.
#ifdef INLN_COMPLEX
#define aimag(z) ( z.y )
#define ctof(z) ( z.x )
#define ftoc(r,i) (( z.x = r, z.y = i ), z)
#define conjg(z) (( z.y = -z.y ), z)
#define cneg(z) ( ( z.x = -z.x, z.y = -z.y ), z)
#else
/* function declarations */
#endif
Note: in the
INLN_COMPLEXbranch, theftocmacro is exactly what provides the only (inline) implementation offtoc. WithoutINLN_COMPLEXtheftocfunction is defined neither as a function nor as a macro (see section 7).
5.3. Precision limits of the _real type (Typedef.h, from <float.h>)
The values depend on whether float or double is behind _real:
| Macro | _real = double |
_real = float |
Meaning |
|---|---|---|---|
REAL_MAX |
DBL_MAX |
FLT_MAX |
The maximum representable value |
REAL_MIN |
DBL_MIN |
FLT_MIN |
The minimum positive value |
REAL_DIG |
DBL_DIG |
FLT_DIG |
The number of significant decimal digits |
REAL_EPSILON |
DBL_EPSILON |
FLT_EPSILON |
The machine epsilon |
REAL_MAX_10_EXP |
DBL_MAX_10_EXP |
FLT_MAX_10_EXP |
The maximum decimal exponent |
REAL_MIN_10_EXP |
DBL_MIN_10_EXP |
FLT_MIN_10_EXP |
The minimum decimal exponent |
REAL_MAX is used directly in cdiv as an overflow indicator on division by zero.
5.4. Mathematical and physical constants (Typedef.h)
| Constant | Value | Meaning |
|---|---|---|
PI |
(_real)3.141592653589793 |
The number π |
MU_NUL |
(_real)12.56637e-7 |
The magnetic constant μ₀ (H/m) |
EPSILON_NUL |
(_real)8.85418757e-12 |
The electric constant ε₀ (F/m) |
LIGHT_VEL |
(_real)2.99792458e8 |
The speed of light in vacuum (m/s) |
6. Dependencies
System headers: <stdlib.h>, <math.h>.
Shared project headers (src/Include/): typedef.h (the types _real,
_complex, the constants), complex1.h (the function prototypes, the macros
itocx/ltocx/INLN_COMPLEX).
TMC Suite libraries: the complex library does not depend on other project libraries.
Reverse dependencies: complex.lib is a dependency of the viewers
(Tmcgrout, DiaNapGr, Tmcrtout) and, transitively, of the compute kernels when
working with S-matrices, radiation patterns and fields.
7. Implementation notes
Below are peculiarities of the CMPLXALL.CPP source code, confirmed by direct
reading of the file. They are given neutrally, as facts about the source code.
This is scientific code — here they are not fixed, only recorded.
7.1. cpowf — logarithm of an uninitialized variable
In the cpowf function (around line 212 of CMPLXALL.CPP) the logarithm is taken
of the local variable z, which at that point is not initialized, instead of
the base l:
_complex _far _fortran cpowf( _complex l, _real r )
{
_complex z;
if( l.x == (_real)0 && l.y == (_real)0 )
return( l );
z = clog( z ); // <-- uses the uninitialized z; clog( l ) was expected
z.x = r*z.x;
z.y = r*z.y;
return( cexp(z) );
}
By analogy with cpow (where clog(l) is used) and by the meaning of the l^r
operation, this apparently should be z = clog( l ). In its current form the result
of cpowf depends on the garbage in uninitialized memory and does not correspond to
the mathematical operation. Not fixed (scientific code).
7.2. Absence of a ftoc implementation
The ftoc function is declared in COMPLEX1.H (in the branch without
INLN_COMPLEX), but its implementation is absent from CMPLXALL.CPP. The only
"working" variant is the inline macro ftoc(r,i) in the INLN_COMPLEX branch. Since
the itocx/ltocx macros expand into a call of ftoc, when building without
INLN_COMPLEX any use of them (as well as a direct call of ftoc) will cause an
"unresolved external symbol" linking error.