Справочник по Ada 2012
G.1.1 Комплексные типы
Статическая семантика
Обобщённый библиотечный пакет Numerics.Generic_Complex_Types имеет следующее объявление:
generic
type Real is digits <>;
package Ada.Numerics.Generic_Complex_Types is
pragma Pure(Generic_Complex_Types);
type Real is digits <>;
package Ada.Numerics.Generic_Complex_Types is
pragma Pure(Generic_Complex_Types);
type Complex is
record
Re, Im : Real'Base;
end record;
record
Re, Im : Real'Base;
end record;
type Imaginary is private;
pragma Preelaborable_Initialization(Imaginary);
pragma Preelaborable_Initialization(Imaginary);
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.
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-связь с IEC 559:1989, последний метод не сгенерирует требуемый результат, если одна из компонент комплексного операнда является бесконечной. (Явное умножение бесконечной компоненты на нулевую компоненту, полученную во время повышения, даёт NaN, который распространяется на конечный результат.) Аналогичные рекомендации применяются в случае умножения комплексного операнда на чисто мнимый операнд и в случае деления комплексного операнда на действительный или чисто мнимый операнд.
Аналогично, поскольку обычный математический смысл сложения комплексного операнда и действительного операнда заключается в том, что мнимая компонента остаётся неизменной, реализация не должна выполнять эту операцию, сначала преобразовывая действительный операнд в комплексный тип, а затем выполняя полное комплексное сложение. В реализациях, в которых атрибут Signed_Zeros типа компоненты равен True (и которые, следовательно, соответствуют IEC 559:1989 в отношении обработки знака нуля в предопределённых арифметических операциях), последний метод не сгенерирует требуемый результат, когда мнимая компонента комплексного операнда представляет собой отрицательный нуль. (Явное сложение отрицательного нуля с нулём, полученным во время повышения, даёт положительный нуль.) Аналогичные рекомендации применяются в случае сложения комплексного операнда и чисто мнимого операнда и в случае вычитания комплексного операнда и действительного или чисто мнимого операнда.
Реализации, в которых Real'Signed_Zeros имеет значение True, должны пытаться обеспечить рациональную обработку знаков нулевых результатов и нулевых компонент результатов. В качестве примера, результат функции Argument должен иметь знак мнимой компоненты параметра X, когда точка, представленная этим параметром, лежит на положительной действительной оси; в качестве другого примера, знак мнимой компоненты функции Compose_From_Polar должен быть таким же, как (соответственно, противоположным) знаком параметра Argument, когда этот параметр имеет значение нуль, а параметр Modulus имеет неотрицательное (соответственно, отрицательное) значение.