При вычислении sinX в указатель Z вместо метки tabl необходимо подставить адрес начала таблицы sin_tabl, а при вычислении arcsinX, соответственно arcsin_tabl.
Каждая из таблиц просчитана для 128 значений функции (256 б во FLASH-памяти программ) в диапазоне изменения аргумента 0…90° для sinX и 0…1 для arcsinX. Фиксированный шаг в таблице sinX d=(90/128)° ≈ 0.7031°, в таблице arcsinX – d = 1/128 ≈ 0.00781.
Данные хранятся в виде 16-разрядных беззнаковых целых чисел, полученных в результате умножения sinX (arcsinX) на 32768 (их можно рассматривать и как беззнаковые дробные числа с фиксированной запятой в формате (1.15)).
Например, значению sinX для угла 45° после табличной конвертации будет соответствовать 32768*0.7071 ≈ 23710 = 0x5A82. После чего умножение числа k на sin45°, в рамках целочисленной арифметики будет выглядеть совсем просто
k*sin45° = (k*23710)/ 32768 = (k*23710) >> 15.
Аргумент – это тоже 2-байтовая величина в которой под целую и дробную части отводится по одному байту (дробное число в формате (8.8)).
Рассмотрим пример вычисления угла по двум известным сторона с помощью функции arcsinX. Обе стороны a и b кодируются 16-разрядными числами, которые размещены в регистрах ah:al (прилежащий катет) и bh:bl (гипотенуза). Естественно, что всегда должно соблюдаться условие a/b ≤ 1 и b > 0.
.def al = R2 ;младший байт значения катета .def ah = R3 ;старший байт значения катета .def bl = R4 ;младший байт значения гипотенузы .def bh = R5 ;старший байт значения гипотенузы .def arg1 = R16 ;вспомогательные регистры будут .def arg2 = R17 ; использоваться в подпрограммах .def arg3 = R18 ;деления и табличной конвертации .def arg4 = R19 .def div1 = R23 ;вспомогательные регистры будут .def div2 = R24 ;использоваться в подпрограмме деления .
Возьмем произвольные значения сторон (ah:al = 735 = 0x02DF, bh:bl = 1015 = 0x03F7) для того, чтобы можно было проследить заходом вычислений.
Местоположения аргумента в таблице необходимо определить делением
(a/b) / d = (a/b) / (1/128) = (128*a)/b , для чего удобно использовать подпрограмму div32_16 (см. Беззнаковые числа):
mov div1,bl ;заносим в 2-байтовый делитель div2:div1 mov div2,bh ;значение стороны b clr arg1 ;заносим в 4-байтовое делимое clr arg2 ;arg4: arg3: arg2: arg1 произведение 128*a mov arg3,al mov arg4,ah lsr arg4 ror arg3 ror arg2 rcall div32_16 ;вызываем подпрограмму деления
На выходе из подпрограммы div32_16 в регистрах arg2: arg1 окажется значение аргумента, необходимое для подпрограммы табличного преобразования. В нашем случае arg2:arg1 = 0x5CB0. Это означает, что искомое значение функции будет находится между элементами с индексами 91 и 92 (0x5B и x5C) в таблице arcsin_tabl, т.е. между 0x66A8 и 0x681A.
rcall tbl_func ;вызываем подпрограмму табличной конвертации .
На выходе из подпрограммы в регистрах arg3:arg2 получим окончательное значение 32768*arcsinX = 0x67A6 откуда arcsinX = 0.80975 рад. Точный расчет дает arcsin(a/b) = arcsin(735/1015) ≈ 0.80978 рад, что расходится с предыдущим результатом менее чем на 0.004%.
Таблицы sinX и arcsinX достаточно универсальны. Используя общие тригонометрические соотношения их можно использовать для вычисления
cosX = sin(90°-X),
tgX = sinX/sin(90°-X),
сtgX = sin(90°-X)/sinX и.др.
Речь здесь идет, конечно, только о первой четверти тригонометрического круга. Знак функций во всех остальных случаях надо будет контролировать отдельно.
Перейти к следующей части: Сортировка - Отыскание минимального и максимального элементов
Комментарии (0) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация