Библиотека 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 > 00; z.y == 0, z.x < 0−π;
  • в остальных случаях за основу берётся atan(z.y/z.x) с поправками по знакам z.x, z.y (вычитание или π).

_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) — число.
  • Возврат: _realm·√((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) — число.
  • Возврат: _realz.x² + z.y² (квадрат модуля без извлечения корня).

_real csqsub(_complex z)

Масштабированная разность квадратов компонент.

  • Параметры: z (_complex) — число.
  • Возврат: _realm²·((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.CPP and the shared headers src/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.CPP is translated exactly as C++), Typedef.h does not declare its own structure but includes <math.h>. In that case the struct _complex built into the MSVC compiler's CRT from <math.h> with fields double x, y is used. Access to the components in all functions is done uniformly — z.x (the real part) and z.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 _real is defined as float, while in the C++ build _complex is taken from the CRT <math.h> with fields double x, y, the types of the structure components and _real diverge. The source code contains explicit casts to (_real) (for example, in aimag, 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, _fortran and similar macros. In the signatures of the original header the functions are decorated with the _far and _fortran attributes (for example, _real _far _fortran aimag( _complex )). These are remnants of the memory models and calling conventions of 16/32-bit code. In Typedef.h all 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. See COMPLEX1.H for 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 from CMPLXALL.CPP — only a commented-out inline variant under the INLN_COMPLEX macro is found in the header. When linking without INLN_COMPLEX, a reference to ftoc will cause an unresolved-symbol error.

_complex conjg(_complex z)

Complex conjugation: changes the sign of the imaginary part.

  • Parameters: z (_complex) — the number.
  • Return: _complex with the value (z.x, −z.y).

_complex cneg(_complex z)

Unary minus: changes the sign of both components.

  • Parameters: z (_complex) — the number.
  • Return: _complex with 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 of int (real i, imaginary j);
  • ltocx(i, j) — from a pair of long (real i, imaginary j).

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: _complex with 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: _complex with 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: _complex with 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 as cexp(cmul(r, clog(l))).
  • Special case: when l == (0, 0), l is 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), l is 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: 1 if l.x == r.x and l.y == r.y (component-wise equality); otherwise 0.

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 of asin is [−π/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 > 00; 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 of z.x, z.y (subtracting 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 magnitude m·√((z.x/m)² + (z.y/m)²), where m = max(|z.x|, |z.y|). When m == 0, 0 is 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: _realm·√((z.x/m)² − (z.y/m)²), where m = max(|z.x|, |z.y|). When m == 0, 0 is 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: _realz.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: _realm²·((z.x/m)² − (z.y/m)²), where m = max(|z.x|, |z.y|). When m == 0, 0 is returned. Mathematically equal to z.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 is arg_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 (via arg_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 == 0 the exponential factor equals 1; when z.y == 0 the result is a purely real number e^{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_COMPLEX branch, the ftoc macro is exactly what provides the only (inline) implementation of ftoc. Without INLN_COMPLEX the ftoc function 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.