Czy jest szybsza funkcja sinusoidalna?

25

Pracuję nad generacją hałasu perlin 3d. Biblioteka C # Math wydaje się przesadą w tym, czego potrzebuję, ponieważ większość jej funkcji wykorzystuje podwójną precyzję. Używam Math.Sin () w kilku miejscach, aby wygenerować szum. Czy ktoś wie o szybszej funkcji sinusa?

użytkownik2709
źródło

Odpowiedzi:

32

Możesz użyć paraboli do przybliżenia wartości funkcji sinusoidalnej. Ma to tę zaletę, że korzenie mają dokładnie -pi / 2 i pi / 2, co zwykle nie ma miejsca w przypadku innych szybkich przybliżeń opartych na TaylorSeries lub MaclaurinSeries .

public float Sin(float x)
{
    const float B = 4 / PI;
    const float C = -4 / (PI*PI);

    return -(B * x + C * x * ((x < 0) ? -x : x));
} 

Oto porównanie z rzeczywistą funkcją sinusoidy:

alternatywny tekst

zfedoran
źródło
3
To jest rzeczywiście świetne rozwiązanie. Oto doskonały artykuł z devmaster.net, który opisuje, dlaczego to działa i podaje kilka szczegółów implementacyjnych: devmaster.net/forums/showthread.php?t=5784
reverbb
Nie wiem o C #, ale funkcja abs () w większości środowisk C prawdopodobnie będzie zoptymalizowana szybciej niż gałąź (operator?:).
3
Usunąłem wywołanie Math.Abs ​​(), ponieważ założyłem, że ten kod może działać na Xbox 360 lub Windows Phone 7. Kompilator JIT na Xbox 360 niczego nie wstawia. Wywołanie Math.Abs ​​() jest w rzeczywistości droższe.
zfedoran
@reverbb Link to 404. Oto kopia z pamięci podręcznej.
Daniel Pendergast
1
@zfedoran Dlaczego negujesz wartość zwracaną? Wygląda na ujemną falę sinusoidalną.
Daniel Pendergast
12

Jaki jest zakres wartości wejściowych dla funkcji sin () ? Wydaje się, że do tego, do czego go używasz, mogą być ograniczone, co oznacza, że ​​możesz wstępnie obliczyć wartości . Na przykład, jeśli zaokrąglasz wartości wejściowe do najbliższego stopnia, masz tylko 360 możliwych wartości - wystarczy je wstępnie obliczyć i zapisać w tabeli.

Jeśli potrzebujesz nieco więcej wartości, powiedzmy z dokładnością do jednego miejsca po przecinku, możesz interpolować z tabeli - nie znam szumu perlin , ale słowo „szum” wydaje się wskazywać, że nie wymaga ono dużej dokładności. :) (Możesz też po prostu zrobić większy stół, 3600 wpisów to niewiele miejsca).

cyklop
źródło
3
Jeśli najważniejsza jest szybkość, a nie masz nic przeciwko poświęceniu odrobiny dokładności, to najlepsza odpowiedź.
AttackingHobo
1
Nie wiem o „najlepszym” - jak pokazano w innej odpowiedzi, możesz uzyskać kolejne bardzo dobre przybliżenie w pięciu operacjach + abs (których prędkość zależy od twojego arch / kompilatora, ale często jest bez rozgałęzienia). Jeśli tabela odnośników nie znajduje się w pamięci podręcznej, będzie znacznie wolniejsza.