Справочник по Ada 95
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;
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 составляет примерно от -PI до PI (-Cycle/2.0 до Cycle/2.0, если задан параметр Cycle). Когда точка, представленная параметром X, лежит на отрицательной оси действительных чисел, результат приблизительно
- PI (соответственно, -PI), если знак мнимой составляющей X положителен (соответственно, отрицателен), если Real'Signed_Zeros – True;
- PI, если 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 имеет неотрицательное (соответственно, отрицательное) значение.