Справочник по Ada (Ada 2022)
G.1.1 Типы комплексных чисел
Статическая семантика
В обобщенном пакете библиотеки Numerics.Generic_Complex_Types содержится следующее объявление:
generic
type Real is digits <>;
package Ada.Numerics.Generic_Complex_Types
with Pure, Nonblocking is
type Real is digits <>;
package Ada.Numerics.Generic_Complex_Types
with Pure, Nonblocking is
type Complex is
record
Re, Im : Real'Base;
end record;
record
Re, Im : Real'Base;
end record;
type Imaginary is private
with Preelaborable_Initialization;
with Preelaborable_Initialization;
i : constant Imaginary;
j : constant Imaginary;
j : constant Imaginary;
function Re (X : Complex) return Real'Base;
function Im (X : Complex) return Real'Base;
function Im (X : Imaginary) return Real'Base;
function Im (X : Complex) return Real'Base;
function Im (X : Imaginary) return Real'Base;
procedure Set_Re (X : in out Complex;
Re : in Real'Base);
procedure Set_Im (X : in out Complex;
Im : in Real'Base);
procedure Set_Im (X : out Imaginary;
Im : in Real'Base);
Re : in Real'Base);
procedure Set_Im (X : in out Complex;
Im : in Real'Base);
procedure Set_Im (X : out Imaginary;
Im : in Real'Base);
function Compose_From_Cartesian (Re, Im : Real'Base) return Complex;
function Compose_From_Cartesian (Re : Real'Base) return Complex;
function Compose_From_Cartesian (Im : Imaginary) return Complex;
function Compose_From_Cartesian (Re : Real'Base) return Complex;
function Compose_From_Cartesian (Im : Imaginary) return Complex;
function Modulus (X : Complex) return Real'Base;
function "abs" (Right : Complex) return Real'Base renames Modulus;
function "abs" (Right : Complex) return Real'Base renames Modulus;
function Argument (X : Complex) return Real'Base;
function Argument (X : Complex;
Cycle : Real'Base) return Real'Base;
function Argument (X : Complex;
Cycle : Real'Base) return Real'Base;
function Compose_From_Polar (Modulus, Argument : Real'Base)
return Complex;
function Compose_From_Polar (Modulus, Argument, Cycle : Real'Base)
return Complex;
return Complex;
function Compose_From_Polar (Modulus, Argument, Cycle : Real'Base)
return Complex;
function "+" (Right : Complex) return Complex;
function "-" (Right : Complex) return Complex;
function Conjugate (X : Complex) return Complex;
function "-" (Right : Complex) return Complex;
function Conjugate (X : Complex) return Complex;
function "+" (Left, Right : Complex) return Complex;
function "-" (Left, Right : Complex) return Complex;
function "*" (Left, Right : Complex) return Complex;
function "/" (Left, Right : Complex) return Complex;
function "-" (Left, Right : Complex) return Complex;
function "*" (Left, Right : Complex) return Complex;
function "/" (Left, Right : Complex) return Complex;
function "**" (Left : Complex; Right : Integer) return Complex;
function "+" (Right : Imaginary) return Imaginary;
function "-" (Right : Imaginary) return Imaginary;
function Conjugate (X : Imaginary) return Imaginary renames "-";
function "abs" (Right : Imaginary) return Real'Base;
function "-" (Right : Imaginary) return Imaginary;
function Conjugate (X : Imaginary) return Imaginary renames "-";
function "abs" (Right : Imaginary) return Real'Base;
function "+" (Left, Right : Imaginary) return Imaginary;
function "-" (Left, Right : Imaginary) return Imaginary;
function "*" (Left, Right : Imaginary) return Real'Base;
function "/" (Left, Right : Imaginary) return Real'Base;
function "-" (Left, Right : Imaginary) return Imaginary;
function "*" (Left, Right : Imaginary) return Real'Base;
function "/" (Left, Right : Imaginary) return Real'Base;
function "**" (Left : Imaginary; Right : Integer) return Complex;
function "<" (Left, Right : Imaginary) return Boolean;
function "<=" (Left, Right : Imaginary) return Boolean;
function ">" (Left, Right : Imaginary) return Boolean;
function ">=" (Left, Right : Imaginary) return Boolean;
function "<=" (Left, Right : Imaginary) return Boolean;
function ">" (Left, Right : Imaginary) return Boolean;
function ">=" (Left, Right : Imaginary) return Boolean;
function "+" (Left : Complex; Right : Real'Base) return Complex;
function "+" (Left : Real'Base; Right : Complex) return Complex;
function "-" (Left : Complex; Right : Real'Base) return Complex;
function "-" (Left : Real'Base; Right : Complex) return Complex;
function "*" (Left : Complex; Right : Real'Base) return Complex;
function "*" (Left : Real'Base; Right : Complex) return Complex;
function "/" (Left : Complex; Right : Real'Base) return Complex;
function "/" (Left : Real'Base; Right : Complex) return Complex;
function "+" (Left : Real'Base; Right : Complex) return Complex;
function "-" (Left : Complex; Right : Real'Base) return Complex;
function "-" (Left : Real'Base; Right : Complex) return Complex;
function "*" (Left : Complex; Right : Real'Base) return Complex;
function "*" (Left : Real'Base; Right : Complex) return Complex;
function "/" (Left : Complex; Right : Real'Base) return Complex;
function "/" (Left : Real'Base; Right : Complex) return Complex;
function "+" (Left : Complex; Right : Imaginary) return Complex;
function "+" (Left : Imaginary; Right : Complex) return Complex;
function "-" (Left : Complex; Right : Imaginary) return Complex;
function "-" (Left : Imaginary; Right : Complex) return Complex;
function "*" (Left : Complex; Right : Imaginary) return Complex;
function "*" (Left : Imaginary; Right : Complex) return Complex;
function "/" (Left : Complex; Right : Imaginary) return Complex;
function "/" (Left : Imaginary; Right : Complex) return Complex;
function "+" (Left : Imaginary; Right : Complex) return Complex;
function "-" (Left : Complex; Right : Imaginary) return Complex;
function "-" (Left : Imaginary; Right : Complex) return Complex;
function "*" (Left : Complex; Right : Imaginary) return Complex;
function "*" (Left : Imaginary; Right : Complex) return Complex;
function "/" (Left : Complex; Right : Imaginary) return Complex;
function "/" (Left : Imaginary; Right : Complex) return Complex;
function "+" (Left : Imaginary; Right : Real'Base) return Complex;
function "+" (Left : Real'Base; Right : Imaginary) return Complex;
function "-" (Left : Imaginary; Right : Real'Base) return Complex;
function "-" (Left : Real'Base; Right : Imaginary) return Complex;
function "*" (Left : Imaginary; Right : Real'Base) return Imaginary;
function "*" (Left : Real'Base; Right : Imaginary) return Imaginary;
function "/" (Left : Imaginary; Right : Real'Base) return Imaginary;
function "/" (Left : Real'Base; Right : Imaginary) return Imaginary;
function "+" (Left : Real'Base; Right : Imaginary) return Complex;
function "-" (Left : Imaginary; Right : Real'Base) return Complex;
function "-" (Left : Real'Base; Right : Imaginary) return Complex;
function "*" (Left : Imaginary; Right : Real'Base) return Imaginary;
function "*" (Left : Real'Base; Right : Imaginary) return Imaginary;
function "/" (Left : Imaginary; Right : Real'Base) return Imaginary;
function "/" (Left : Real'Base; Right : Imaginary) return Imaginary;
private
type Imaginary is new Real'Base;
i : constant Imaginary := 1.0;
j : constant Imaginary := 1.0;
i : constant Imaginary := 1.0;
j : constant Imaginary := 1.0;
end Ada.Numerics.Generic_Complex_Types;
Пакет библиотеки Numerics.Complex_Types объявлен как чистый и определяет те же типы, константы и подпрограммы, что и Numerics.Generic_Complex_Types, за исключением того, что предварительно определённый тип Float систематически заменяет Real'Base на протяжении всего текста. Аналогичным образом определяются необобщенные эквиваленты Numerics.Generic_Complex_Types для каждого из других предварительно определенных типов с плавающей точкой с именами Numerics.Short_Complex_Types, Numerics.Long_Complex_Types и т. д.
Complex — это видимый тип с декартовыми компонентами.
Imaginary — это закрытый тип; его полный тип получен из Real'Base.
Арифметические операции и функции Re, Im, Modulus, Argument и Conjugate имеют свои обычные математические значения. При применении к параметру чисто мнимого типа функция «мнимой части» Im возвращает значение его параметра, как соответствующее действительное значение. Остальные подпрограммы имеют следующие значения:
- Процедуры Set_Re и Set_Im заменяют указанный компонент комплексного параметра заданным вещественным значением; при применении к параметру чисто мнимого типа процедура Set_Im заменяет значение этого параметра мнимым значением, соответствующим заданному вещественному значению.
- Функция Compose_From_Cartesian создает комплексное значение из заданных действительной и мнимой составляющих. Если задан только один компонент, другой компонент неявно равен нулю.
- Функция Compose_From_Polar создает комплексное значение из заданного модуля (радиуса) и аргумента (угла). При положительном (соответственно отрицательном) значении параметра Modulus результат — комплексное значение, представленное точкой в комплексной плоскости, находящейся на расстоянии от начала координат, заданном абсолютным значением Modulus, и образующей угол, отсчитываемый против часовой стрелки от положительной (соответственно отрицательной) вещественной оси, заданный значением параметра Argument.
При указании параметра Cycle результат функции Argument и параметр Argument функции Compose_From_Polar измеряются в единицах, таких, что полный цикл вращения имеет заданное значение; в противном случае они измеряются в радианах.
Вычисленные результаты математических многозначных функций делаются однозначными с помощью следующих соглашений, которые предполагают главную ветвь:
- Результат функции Modulus неотрицателен.
- Результат функции Argument находится в квадранте, содержащем точку в комплексной плоскости, представленную параметром X. Это может быть любой квадрант (I–IV); таким образом, диапазон функции Argument приблизительно от –π до π (–Cycle/2.0 до Cycle/2.0, если задан параметр Cycle). Когда точка, представленная параметром X, лежит на отрицательной вещественной оси, результат приближается к
π (соответственно –π) при положительном (соответственно отрицательном) знаке мнимой составляющей X, если Real'Signed_Zeros = True;
π, если Real'Signed_Zeros = False.
- Поскольку результат, лежащий на или около одной из осей, может не быть точно представлен, присущая вычислению приближенность может поместить его в смежный квадрант, близко к, но по другую сторону оси.
Динамическая семантика
Исключение Numerics.Argument_Error генерируется функциями Argument и Compose_From_Polar со специфицированным циклом, сигнализируя о значении параметра вне области соответствующей математической функции, когда значение параметра Cycle равно нулю или отрицательно.
Исключение Constraint_Error генерируется оператором деления, когда значение правого операнда равно нулю, и оператором возведения в степень, когда значение левого операнда равно нулю, а значение показателя отрицательно, при условии, что Real'Machine_Overflows = True; когда Real'Machine_Overflows = False, результат не определён. Constraint_Error также может быть сгенерирован, когда конечный результат переполняется (см. G.2.6).
Требования к реализации
При реализации Numerics.Generic_Complex_Types диапазон промежуточных значений, допускаемых при вычислении конечного результата, не должен быть изменён никаким ограничением диапазона типа Real.
В следующих случаях вычисление комплексной арифметической операции должно давать предписанный результат, при условии, что вышеуказанные правила не требуют генерирования исключения:
- Результаты функций Re, Im и Compose_From_Cartesian являются точными.
- Действительная (соответственно мнимая) составляющая результата бинарного оператора сложения, дающего результат комплексного типа, является точной, если один из его операндов — чисто мнимого (соответственно вещественного) типа.
- Вещественная (соответственно, мнимая) компонента результата бинарного оператора вычитания, который даёт результат комплексного типа, точна, когда его правый операнд имеет чисто мнимый (соответственно, вещественный) тип.
- Вещественная компонента результата функции Conjugate для комплексного типа точна.
- Когда точка в комплексной плоскости, представленная параметром X, лежит на неотрицательной вещественной оси, функция Argument даёт результат ноль.
- Когда значение параметра Modulus равно нулю, функция Compose_From_Polar даёт результат ноль.
- Когда значение параметра Argument равно целому кратному четверти цикла, результат функции Compose_From_Polar с указанным циклом лежит на одной из осей. В этом случае одна из его компонент равна нулю, а другая имеет величину параметра Modulus.
- Возведение в степень с нулевым показателем даёт значение один. Возведение в степень с единичным показателем даёт значение левого операнда. Возведение значения один в степень даёт значение один. Возведение значения ноль в степень даёт значение ноль, при условии, что показатель не равен нулю. Когда левый операнд имеет чисто мнимый тип, одна из компонент результата оператора возведения в степень равна нулю.
Когда результат или компонента результата любого оператора из Numerics.Generic_Complex_Types имеет математическое определение в терминах одной арифметической или реляционной операции, этот результат или компонента результата демонстрирует точность соответствующей операции типа Real.
Другие требования к точности для функций Modulus, Argument и Compose_From_Polar, а также требования к точности умножения пары комплексных операндов или деления на комплексный операнд, которые применяются только в строгом режиме, приведены в G.2.6.
Знак нулевого результата или нулевой компоненты результата, полученного в результате комплексной арифметической операции или функции, определяется реализацией, когда Real'Signed_Zeros имеет значение True.
Разрешения на реализацию
Негенерические эквивалентные пакеты могут быть фактическими экземплярами генерического пакета для соответствующего предопределённого типа, хотя это не обязательно.
Реализации могут получить результат возведения в степень комплексного или чисто мнимого операнда путём многократного комплексного умножения, с произвольным объединением множителей и возможной конечной комплексной реципрокацией (когда показатель степени отрицательный). Реализации также могут получить результат возведения в степень комплексного операнда, но не чисто мнимого операнда, путём преобразования левого операнда в полярное представление; возведения модуля в заданную степень; умножения аргумента на заданную степень; и преобразования обратно к декартовому представлению. Из-за этой свободы реализации, нет требований к точности комплексного возведения в степень (за исключением предписанных результатов, указанных выше, которые применимы независимо от выбранного метода реализации).
Рекомендации по реализации
Поскольку обычный математический смысл умножения комплексного операнда и вещественного операнда заключается в масштабировании обеих компонент первого операнда на второй, реализация не должна выполнять эту операцию путём предварительного повышения вещественного операнда до комплексного типа и последующего выполнения полного комплексного умножения. В системах, которые в будущем будут поддерживать Ada-связь с ISO/IEC 60559:2020, последний метод не будет генерировать требуемый результат, когда одна из компонент комплексного операнда является бесконечностью. (Явное умножение бесконечной компоненты на нулевую компоненту, полученную во время повышения, даёт NaN, который распространяется в конечный результат.) Аналогичные рекомендации применяются в случае умножения комплексного операнда и чисто мнимого операнда, а также в случае деления комплексного операнда на вещественный или чисто мнимый операнд.
Аналогично, поскольку обычный математический смысл сложения комплексного операнда и вещественного операнда заключается в том, что мнимая компонента остаётся неизменной, реализация не должна выполнять эту операцию путём предварительного повышения вещественного операнда до комплексного типа и последующего выполнения полного комплексного сложения. В реализациях, в которых атрибут Signed_Zeros типа компоненты имеет значение True (и которые, следовательно, соответствуют ISO/IEC 60559:2020 в отношении обработки знака нуля в предопределённых арифметических операциях), последний метод не будет генерировать требуемый результат, когда мнимая компонента комплексного операнда является отрицательно-знаковым нулём. (Явное сложение отрицательного нуля с нулём, полученным во время повышения, даёт положительный ноль.) Аналогичные рекомендации применяются в случае сложения комплексного операнда и чисто мнимого операнда, а также в случае вычитания комплексного операнда и вещественного или чисто мнимого операнда.
Реализации, в которых Real'Signed_Zeros имеет значение True, должны стремиться к рациональному рассмотрению знаков нулевых результатов и компонент результата. Например, результат функции Argument должен иметь знак мнимой компоненты параметра X, когда точка, представленная этим параметром, лежит на положительной вещественной оси; или, знак мнимой компоненты функции Compose_From_Polar должен быть таким же, как (соответственно, противоположным) знаку параметра Argument, когда этот параметр имеет значение ноль, а параметр Modulus имеет неотрицательное (соответственно, отрицательное) значение.