CORDIC для квадратных корней
Я искал алгоритм CORDIC в режиме гиперболического вращения, чтобы найти квадратный корень переменной. Я не уверен, что мои начальные переменные должны быть (x0, y0, z0), чтобы найти квадратный корень. Я читал некоторые статьи, ссылаясь на то, что для нахождения sqrt(a) необходимо установить начальные значения a+1,a-1,0 для x0, y0 и z0 соответственно. Другие говорят, что это должно быть +0,25,a-0,25,0. Я очень смущен этим
Кто-нибудь может помочь?
double x = (64.0+1);
double y = (64.0-1);
double z = 0;
double k = 3;
double n = 1;
while(n <= 20 ){
double xn = pow(2.0,-1.0*n) * x;
double yn = pow(2.0,-1.0*n) * y;
if(y < 0){
x = x + xn;
y = y + yn;
z = z - atanh(pow(2.0,-1.0*n));
}
else
{
x = x - xn;
y = y - yn;
z = z + atanh(pow(2.0,-1*n));
}
if(k > 0){
k = k-1;
}
else{
k = 3;
if(y < 0){
x = x + xn;
y = y + yn;
z = z - atanh(pow(2.0,-1.0*n));
}
else
{
x = x - xn;
y = y - yn;
z = z + atanh(pow(2.0,-1.0*n));
}
}
n++;
cout << "x: " << x << " y: " << y << " z: " << z << endl;
}
РЕДАКТИРОВАТЬ * Наряду с компенсацией за 3j+1 повторов, CORDIC требует выполнить цикл дважды в таких случаях, как n = 4,13,40, ... Я обновил свой код, чтобы компенсировать это, но он все еще не работает. Я использую гиперболическое вращение в векторном режиме, который переменная d
должно быть основано на знаке у
РЕДАКТИРОВАТЬ * Оказывается, что CORDIC может дать сбой при вычислении больших значений квадратного корня, поэтому вам нужно нормализовать число, которое вы пытаетесь найти, от квадратного корня до диапазона от 0,5 до 2, а затем уменьшить ответ обратно.
2 ответа
Вам следует нормализовать число, в котором вы выполняете квадратный корень, до [0,5,2) диапазона, а затем соответственно уменьшить его.
начальные значения должны быть установлены на +1,a-1,0 для x0,y0 и z0 соответственно. Другие говорят, что это должно быть +0,25,a-0,25,0. Я очень смущен этим
Конечный результат sqrt((a+1)^2 - (a-1)^2)
или же sqrt((a+0.25)^2 - (a-0.25)^2)
, В любом случае a^2
условия отменяются и постоянные условия отменяются. Единственное отличие - первая версия возвращается sqrt(4a)
или же 2sqrt(a)
а второй возвращается sqrt(a)
непосредственно. Я не знаю численных причин, почему один или другой случай может быть предпочтительным.
Изменить: ваша ошибка устанавливается d
основанный на y
должно быть основано на z
,
В коде есть несколько ошибок!
- Обмен переменными не производится.
x = x + xn;
y = y + yn;
должно быть:
x = x + yn;
y = y + xn;
- Итерации 4 и 13 не повторяются должным образом. В этих ветках необходимо пересчитать следующее:
xn = pow(2.0,-1.0*n) * y;
yn = pow(2.0,-1.0*n) * x;
- Корректировку масштаба следует производить на выходе (
x/2*1.207497
).
См. Здесь некрасивый отлаженный, но рабочий код:https://godbolt.org/z/ma4dCV
Отметим также, что нет необходимости во всем z
канал (https://mathworks.com/help/fixedpoint/examples/compute-square-root-using-cordic.html).