Я отрисовываю 500×500 очков в режиме реального времени.
Я должен вычислить положение точек, используя функции atan () и sin (). Используя atan () и sin () я получаю 24 кадра в секунду (кадров в секунду).
float thetaC = atan(value);
float h = (value) / (sin(thetaC)));
Если я не использую грех (), я получаю 52 кадра в секунду.
и если я не использую atan (), я 30 кадров в секунду.
Итак, большая проблема с грехом (). Как я могу использовать версию Fast Sin. Могу ли я создать таблицу поиска для этого? У меня нет конкретных значений для создания LUT. что я могу сделать в этой ситуации?
PS: Я также попробовал функцию быстрого греха ASM, но не получил никакой разницы.
Благодарю.
Это зависит от точности, которая вам нужна. Максимальная производная от греха равна 1, поэтому, если x1 и x2 находятся в эпсилоне друг от друга, то sin (x1) и sin (x2) также находятся в эпсилоне. Если вам просто нужна точность с точностью, скажем, 0,001, то вы можете создать справочную таблицу из 1000 * PI = 3142 точек и просто найти значение, наиболее близкое к нужному. Это может быть быстрее, чем то, что делает нативный код, поскольку нативный код (вероятно) использует таблицу поиска для полиномиальных коэффициентов, а затем интерполирует, и поскольку эта таблица может быть достаточно маленькой, чтобы легко оставаться в кеше.
Если вам нужна полная точность во всем диапазоне, то, вероятно, нет ничего лучше, чем вы можете сделать.
Если вы хотите, вы можете также создать справочную таблицу поверх (1 / sin (x)), поскольку это ваша реальная интересующая функция. В любом случае вам нужно быть осторожным в отношении sin (x) = 0, поскольку небольшая ошибка в sin (x) может привести к большой ошибке в 1 / sin (x). Определение толерантности к ошибкам важно для определения возможных комбинаций клавиш.
Вы создали бы таблицу поиска с чем-то вроде:
float *table = malloc(1000 * sizeof(float));
for(int i = 0; i < 1000; i++){
table[i] = sin(i/1000.0);
}
и будет иметь доступ к этому что-то вроде
void fastSin(float x){
int index = x * 1000.0;
return table[index];
}
Этот код не завершен (и потерпит крах за что-либо за пределами 0 < Икс < 1, из-за границ массива), но вы должны начать.
Подожди секунду….
У вас есть треугольник, вы вычисляете гипотонуса. Во-первых, вы принимаете atan(value)
чтобы получить угол, а затем с помощью value
снова с sin
вычислить h
, Итак, у нас есть сценарий, где одна сторона треугольника равна 1:
/|
h / | value
/ |
/C__|
1
Все, что вам действительно нужно сделать, это рассчитать h = sqrt(value*value + 1);
… Но потом, sqrt
не самая быстрая функция вокруг.
Возможно, я упустил суть или вы что-то упустили. Я всегда использовал справочные таблицы для sin
а также cos
и нашел их быстрыми. Если вы не знаете значения заранее, тогда вам нужно приблизиться, но это означает умножение, усечение до целого числа (и, возможно, преобразование знака), чтобы получить индекс массива. Если вы можете преобразовать свои единицы в целочисленные значения (эффективно превращая числа с плавающей точкой в фиксированную точку), это сделает поиск еще быстрее.
За грех (но не за Атан) вы можете стать проще, чем за столом — просто создайте
float sin_arr[31416]; //Or as much precision as you need
for (int i=0; i<31416; ++i)
sin_arr[i] = sin( i / 10000.0 );
//...
float h = (value) / sin_arr[ (int)(thetaC*10000.0) % 31416 ];
Я предполагаю, что это даст вам улучшение скорости.
Я случайно наткнулся на эту библиотеку JavaScript с открытым исходным кодом, которая включает в себя интересное приближение тригонометрических функций (грех & загар среди прочего).
Вроде бы быстро и точно.
Возможно, вы могли бы переписать его на с / с ++.
Библиотека: http://danisraelmalta.github.io/Fmath/