Existe-t-il une fonction sinus plus rapide?

25

Je travaille sur le bruit perlin de génération 3d. La bibliothèque C # Math semble exagérée pour ce dont j'ai besoin car la plupart de ses fonctions utilisent la double percision. J'utilise Math.Sin () à plusieurs endroits pour générer du bruit. Quelqu'un connaît-il une fonction sinus plus rapide?

user2709
la source

Réponses:

32

Vous pouvez utiliser une parabole pour approximer la valeur de la fonction sinus. Cela a l'avantage d'avoir les racines exactement à -pi / 2 et pi / 2, ce qui n'est généralement pas le cas avec d'autres approximations rapides basées sur TaylorSeries ou 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));
} 

Voici une comparaison avec la fonction sinusoïdale réelle:

texte alternatif

zfedoran
la source
3
C'est en effet une excellente solution. Voici un excellent article de devmaster.net qui explique pourquoi cela fonctionne et donne quelques détails d'implémentation: devmaster.net/forums/showthread.php?t=5784
reverbb
Je ne connais pas C #, mais la fonction abs () dans la plupart des environnements C sera probablement plus rapide qu'une branche (l'opérateur?:), Lorsqu'elle est optimisée.
3
J'ai supprimé l'appel Math.Abs ​​() parce que je supposais que ce code pourrait s'exécuter sur la Xbox 360 ou Windows Phone 7. Le compilateur JIT sur Xbox 360 n'inline rien. Un appel à Math.Abs ​​() est en fait plus cher.
zfedoran
@reverbb Link est 404. Voici une copie en cache.
Daniel Pendergast
1
@zfedoran Pourquoi annulez-vous la valeur de retour? Il semble que ce soit une onde sinusoïdale négative.
Daniel Pendergast
12

Quelle est la plage de valeurs d'entrée pour votre fonction sin () ? Pour ce que vous l'utilisez, il semble qu'ils soient limités, ce qui signifie que vous pouvez pré-calculer les valeurs . Par exemple, si vous arrondissez les valeurs d'entrée au degré le plus proche, vous n'avez que 360 ​​valeurs possibles - il suffit de les pré-calculer et de les stocker dans une table.

Si vous avez besoin d'un peu plus de valeurs, disons à une décimale près, vous pouvez interpoler à partir du tableau - je ne connais pas le bruit perlin , mais le mot "bruit" semble indiquer qu'il ne nécessite pas une grande précision. :) (Vous pouvez également créer un tableau plus grand, 3600 entrées ne sont pas beaucoup d'espace).

cyclope
la source
3
Si la vitesse est votre préoccupation numéro un et que cela ne vous dérange pas de sacrifier un peu de précision, c'est la meilleure réponse.
AttackingHobo
1
Je ne sais pas "meilleur" - Comme indiqué dans une autre réponse, vous pouvez obtenir une autre très bonne approximation en cinq opérations + abs (dont la vitesse dépend de votre arch / compilateur, mais est souvent sans branche). Si la table de recherche n'est pas dans le cache, elle sera beaucoup plus lente.