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,

В коде есть несколько ошибок!

  1. Обмен переменными не производится.
     x = x + xn;
     y = y + yn;

должно быть:

     x = x + yn;
     y = y + xn;
  1. Итерации 4 и 13 не повторяются должным образом. В этих ветках необходимо пересчитать следующее:
     xn = pow(2.0,-1.0*n) * y;
     yn = pow(2.0,-1.0*n) * x;
  1. Корректировку масштаба следует производить на выходе (x/2*1.207497).

См. Здесь некрасивый отлаженный, но рабочий код:https://godbolt.org/z/ma4dCV

Отметим также, что нет необходимости во всем zканал (https://mathworks.com/help/fixedpoint/examples/compute-square-root-using-cordic.html).

Другие вопросы по тегам