правила с плавающей запятой

Direct3D поддерживает несколько представлений с плавающей запятой. Все вычисления с плавающей запятой выполняются в соответствии с определённым подмножеством правил IEEE 754 для 32-разрядной одинарной точности.

32-разрядные правила с плавающей запятой

Существует два набора правил: те, которые соответствуют IEEE-754, и те, которые отклоняются от стандарта.

Соблюденные правила IEEE-754

Некоторые из этих правил являются одним вариантом, где IEEE-754 предлагает варианты выбора.

  • Деление на 0 производит +/-INF, за исключением 0/0, что приводит к naN.

  • Логарифм от (+/-) 0 дает -INF.  

    логарифм отрицательного значения (кроме -0) дает NaN.

  • Обратный квадратный корень (rsq) или квадратный корень (sqrt) отрицательного числа производит NaN.  

    Исключение равно -0; sqrt(-0) производит -0, а rsq(-0) производит -INF.

  • INF - INF = NaN

  • (+)INF / (+/-)INF = NaN

  • (+/-)INF * 0 = NaN

  • NaN (любой операнд) любое-значение = NaN

  • Сравнения EQ, GT, GE, LT и LE возвращают FALSE, если один или оба операнда являются NaN.

  • Сравнения игнорируют знак 0 (поэтому +0 равен -0).

  • Сравнение NE, когда один или оба операнда являются NaN, возвращает TRUE.

  • Сравнение любого значения, отличного от NaN, с +/-INF, возвращает правильный результат.

отклонения или дополнительные требования к правилам IEEE-754

  • IEEE-754 требует, чтобы операции с плавающей запятой давали результат, который является ближайшим представляемым значением к бесконечно точному результату, известному как округление до ближайшего четного.

    Direct3D 11 и вверх определяют то же требование, что и IEEE-754: 32-разрядные операции с плавающей запятой создают результат, который находится в пределах 0,5 единицы последней точки (ULP) бесконечно точного результата. Это означает, что, например, оборудование может усечь результаты до 32-разрядного формата, а не выполнять округление до ближайшего четного числа, так как это приведет к ошибке не более 0,5 ULP. Это правило применяется только к добавлению, вычитании и умножению.

    Более ранние версии Direct3D определяют более слабое требование, чем IEEE-754: 32-разрядные операции с плавающей запятой создают результат, который находится в пределах одного единицы последнего места (1 ULP) бесконечно точного результата. Это означает, что, например, аппаратное обеспечение может усечь результаты до 32-разрядных, а не выполнять округление до ближайшего чётного, так как это приведет к ошибке не больше, чем на один ULP.

  • Нет поддержки исключений с плавающей запятой, флагов состояния или триггеров.

  • Денормы преобразуются в ноль, сохраняющий знак, на входе и выходе любой математической операции с плавающей точкой. Исключения создаются для любой операции ввода-вывода или перемещения данных, которая не управляет данными.

  • Состояния, содержащие значения с плавающей запятой, такие как значения Viewport MinDepth/MaxDepth или BorderColor, могут быть предоставлены как денормальные значения и могут быть отброшены или сохранены перед их использованием оборудованием.

  • Операции минимум или максимум выбрасывают денормы для сравнения, но результат может или не может иметь сброшенные денормы.

  • Входные данные NaN для вычисления всегда приводят к NaN на выходе. Но точный битовый шаблон NaN не требуется для того, чтобы оставаться неизменным (если операция не является необработанной инструкцией перемещения , которая не изменяет данные.)

  • Операции min и max, для которых только один операнд является NaN, возвращают другой операнд в результате (вопреки правилам сравнения, которые мы рассмотрели ранее). Это правило IEEE 754R.

    Спецификация IEEE-754R для операций с плавающей запятой min и max указывает, что если одно из входных данных в минимальное или максимальное значение является тихим значением QNaN, результатом операции является другой параметр. Рассмотрим пример.

    min(x,QNaN) == min(QNaN,x) == x (same for max)
    

    Редакция спецификации IEEE-754R приняла другое поведение для min и max, если одно входное значение является "сигнальным" значением SNaN и значением QNaN:

    min(x,SNaN) == min(SNaN,x) == QNaN (same for max)
    
    

    Как правило, Direct3D соответствует стандартам арифметики: IEEE-754 и IEEE-754R. Но в этом случае у нас есть отклонение.

    Арифметические правила в Direct3D 10 и более поздних версиях не делают никаких различий между тихими и сигнальными значениями NaN (QNaN и SNaN). Все значения NaN обрабатываются одинаково. В случае min и max поведение Direct3D для любого значения NaN похоже на то, как QNaN обрабатывается в определении IEEE-754R. (Для полноты — если оба входных данных являются NaN, возвращается любое значение NaN.)

  • Другое правило IEEE 754R заключается в том, что min(-0,+0) == min(+0,-0) == -0 и max(-0,+0) == max(+0,-0) == +0, которое учитывает знак, в отличие от правил сравнения для знаковых нулей (как мы видели ранее). Direct3D рекомендует здесь поведение IEEE 754R, но не применяет его; Результат сравнения нулей может зависеть от порядка параметров, используя сравнение, которое игнорирует знаки.

  • x*1.0f всегда приводит к x (за исключением случаев, когда денормализованные числа подавлены).

  • x/1.0f всегда равен x (за исключением случаев, когда денормализованные числа удалены).

  • x +/- 0.0f всегда результат равен x (за исключением сброса денормализованных значений). Но -0 + 0 = +0.

  • Объединённые операции (такие как mad, dp3) дают результаты, которые не менее точны, чем худшее возможное последовательное упорядочивание вычисления несоединённого варианта операции. Определение наихудшего возможного упорядочивания в целях учёта допустимых отклонений не является фиксированным для данной объединённой операции; это зависит от конкретных значений входных данных. Отдельным шагам в необъединенном расширении допускается погрешность в 1 ULP (или в случае любых инструкций, для которых Direct3D допускает более высокий уровень погрешности, чем 1 ULP, разрешается использовать более высокий уровень).

  • Сплавленные операции соответствуют тем же правилам NaN, что и неисплавленные операции.

  • sqrt и rcp имеют допуск в 1 ULP. Инструкции шейдера на взаимное значение и взаимный квадратный корень, rcp и rsq, имеют свои отдельные требования к расслабленной точности.

  • Операции умножения и деления выполняются с 32-разрядной точностью с плавающей запятой (точность до 0,5 ULP для умножения и 1,0 ULP для обратного деления). Если x/y реализован напрямую, результаты должны иметь большую или равную точность, чем двухэтапный метод.

64-разрядные (двойная точность) правила с плавающей запятой

Аппаратные и дисплейные драйверы опционально поддерживают двойную точность с плавающей запятой. Чтобы указать поддержку, при вызове ID3D11Device::CheckFeatureSupport с D3D11_FEATURE_DOUBLESдрайвер устанавливает DoublePrecisionFloatShaderOps для D3D11_FEATURE_DATA_DOUBLES в значение TRUE. Затем драйвер и оборудование должны поддерживать все инструкции с двойной точностью для чисел с плавающей запятой.

Инструкции по двойной точности соответствуют требованиям к поведению IEEE 754R.

Требуется поддержка генерации денормализованных значений для данных двойной точности (без поведения округления до нуля). Аналогично, инструкции не интерпретируют денормализованные данные как числовое значение со знаком ноль; вместо этого, они учитывают само денормализованное значение.

16-разрядные правила с плавающей запятой

Direct3D также поддерживает 16-разрядные представления чисел с плавающей запятой.

Формат:

  • 1 бит знака (s)в позиции бита MSB
  • 5 бит предвзятой экспоненты (e)
  • 10 бит дроби (f), с дополнительным скрытым битом

Значение float16 (v) следует следующим правилам:

  • если e == 31 и f != 0, то v — NaN независимо от s
  • если e == 31 и f == 0, то v = (-1)s*бесконечность (подписанная бесконечность)
  • Если e находится в диапазоне от 0 до 31, то v = (-1)s*2(e-15)*(1.f)
  • if e == 0 и f != 0, а затем v = (-1)s*2(e-14)*(0.f) (денормализованные числа)
  • если e == 0 и f == 0, то v = (-1)s*0 (знаковый ноль)

32-разрядные правила с плавающей запятой также применимы к 16-разрядным числам с плавающей запятой, с учётом битовой структуры, описанной ранее. Ниже приведены исключения:

  • Точность: Неприведённые операции с 16-разрядными числами с плавающей запятой создают результат, который является ближайшим представляемым значением к бесконечно-точному результату (округление до ближайшего чётного, в соответствии с IEEE-754, применяется к 16-разрядным значениям). 32-разрядные правила с плавающей запятой соответствуют точности в 1 ULP, 16-разрядные правила с плавающей запятой соответствуют точности в 0,5 ULP для несовмещённых операций и 0,6 ULP для совмещённых операций.
  • 16-разрядные числа с плавающей запятой сохраняют денормы.

11-разрядные и 10-разрядные правила с плавающей запятой

Direct3D также поддерживает 11-разрядные и 10-разрядные форматы с плавающей запятой.

Формат:

  • Нет бита знака
  • 5 бит предвзятой экспоненты (e)
  • 6 бит дроби (f) для 11-разрядного формата, 5 бит дроби (f) для 10-разрядного формата с дополнительным скрытым битом в любом случае.

Значение float11/float10 (v) соответствует следующим правилам:

  • если e == 31 и f != 0, то v — NaN
  • если e == 31 и f == 0, то v = +бесконечность
  • значение e от 0 до 31, то v = 2(e-15)*(1.f)
  • если e == 0 и f != 0, то v = *2(e-14)*(0.f) (денормализованные числа)
  • если e == 0 и f == 0, то v = 0 (ноль)

32-разрядные правила с плавающей запятой также содержат 11-разрядные и 10-разрядные числа с плавающей запятой, скорректированные для битового макета, описанного ранее. К исключениям относятся:

  • Точность: 32-разрядные правила с плавающей запятой соответствуют 0,5 ULP.
  • 10/11-разрядные числа с плавающей запятой сохраняют денормализованные значения.
  • Любая операция, результат которой - число меньше нуля, приравнивается к нулю.

Приложения

Ресурсы

текстуры