Если точная точность не требуется, у меня есть быстрое приближение к вам, которое использует 260 байт памяти (вы можете вдвое уменьшить это, но не делать этого).
int ftbl[33]={0,1,1,2,2,4,5,8,11,16,22,32,45,64,90,128,181,256,362,512,724,1024,1448,2048,2896,4096,5792,8192,11585,16384,23170,32768,46340};
int ftbl2[32]={ 32768,33276,33776,34269,34755,35235,35708,36174,36635,37090,37540,37984,38423,38858,39287,39712,40132,40548,40960,41367,41771,42170,42566,42959,43347,43733,44115,44493,44869,45241,45611,45977};
int fisqrt(int val)
{
int cnt=0;
int t=val;
while (t) {cnt++;t>>=1;}
if (6>=cnt) t=(val<<(6-cnt));
else t=(val>>(cnt-6));
return (ftbl[cnt]*ftbl2[t&31])>>15;
}
Вот код для создания таблицы:
ftbl[0]=0;
for (int i=0;i<32;i++) ftbl[i+1]=sqrt(pow(2.0,i));
printf("int ftbl[33]={0");
for (int i=0;i<32;i++) printf(",%d",ftbl[i+1]);
printf("};\n");
for (int i=0;i<32;i++) ftbl2[i]=sqrt(1.0+i/32.0)*32768;
printf("int ftbl2[32]={");
for (int i=0;i<32;i++) printf("%c%d",(i)?',':' ',ftbl2[i]);
printf("};\n");
в диапазоне 1-> 2^20, максимальная погрешность составляет 11, а в диапазоне 1-> 2^30, то около 256. Вы можете использовать большие таблицы и минимизировать это. Стоит отметить, что ошибка всегда будет отрицательной - т. Е. Когда это будет неправильно, значение будет МЕНЬШЕ, чем правильное значение.
Вы можете преуспеть, следуя этому этапу очистки.
Идея достаточно проста: (ab)^0.5 = a^0.b * b^0.5.
Итак, мы берем вход Х = A * B, где А = 2^N и 1 < = В Тогда мы имеем LookupTable для SQRT (2^N), и LookupTable для SQRT (1 < = B < 2). Мы храним поисковик для sqrt (2^N) как целое, что может быть ошибкой (тестирование не показывает никаких негативных последствий), и мы храним поисковую таблицу для sqrt (1 < = B < 2) в 15 бит фиксированной точки.
Мы знаем, что 1 < = SQRT (2^N) < 65536, так что 16bit, и мы знаем, что мы можем на самом деле только умножать 16bitx15bit на ARM, не опасаясь репрессий, так это то, что мы делаем.
С точки зрения реализации, while (t) {cnt ++; t >> = 1;} - это команда с начальным битом (CLB), поэтому, если ваша версия чипсета имеет это, вы победы! Кроме того, инструкция сдвига будет легко реализована с помощью двунаправленного переключателя, если у вас его есть? Там в [N], алгоритм Lg для подсчета высокого набора битого here.
С точкой зрения магических чисел, для изменения размеров таблицы, магическое число для ftbl2 32, хотя отмечает, что (Lg [32] + 1) используется для смещения.
FWIW, хотя я действительно не рекомендую это, вы можете округлить свою общую ошибку с некоторым смещением, а именно: int v1 = fisqrt (val); V1 + = fisqrt (Val-v1 * v1)/16; 16 - сила двух, которая лучше всего работает в диапазоне 1-> 2^24. –