9
votes

Y a-t-il une fonction en C ou C ++ pour faire "saturation" sur un entier

Je fais des graphismes 3D et j'ai un océan ouvert. Pour cet océan, j'ai une matrice représentant l'état de la mer (c'est-à-dire des hauteur des vagues) pour une sous-section rectangulaire de la mer. Le reste de l'océan est plat. Mon problème est que ma mer contrôlée, où il y a des vagues, est positionnée au milieu d'une mer plane ouverte et la discontinuité des bords de ma grille provoque des mauvais artefacts. La raison pour laquelle je ne génère que des vagues pour une sous-section et non la mer entière est que ma fonction de bruit est prohibitive de calculer sur toute la mer (et je sais que la solution la plus facile est d'utiliser une fonction de bruit moins chère comme le bruit simplex, mais ce n'est pas une option).

avoir dit que ma question est vraiment assez simple. Si vous dites que j'ai une grille (AKA Matrix alias 2D) de taille 100x40, et je souhaite trouver la valeur de la position 120x33, je veux simplement prendre le voisin le plus proche, qui serait 100x33. Donc, pour tout nombre qui se trouve à l'extérieur d'une plage donnée, je souhaite que ce nombre soit saturé de se situer dans la plage donnée. Y a-t-il une fonction dans C ou C ++ qui fait cela?

Edit: Les paramètres de position sont de type flotteur

Je sais que je peux faire cela avec quelques déclarations simples, mais cela semble simplement être quelque chose que les bibliothèques standard comprendraient.

c c++

9 commentaires

Il y a des instructions SSE prenant en charge la saturation.


Cela implique-t-il codant en montage? Aussi, puis-je spécifier la plage ou cela juste saturer les gammes des types de données primitive?


Je pense que toute machine moderne devrait pouvoir faire une mer entière sans aucun problème. Mon logiciel ( ORCINA.com/softwareProducts/orcaflex ). En ce sens, il tente de modéliser la physique de manière réaliste.


@David: Ils peuvent et ils le font, mais je reçois mon spectre de la mer sur le réseau à partir du code MATLAB, quel guichet automatique n'est pas compilé, il ne fonctionne donc pas environ 100 fois plus lent que le Native C, et à Matlab, cela est plus difficile à faire. en temps réel pour toute une mer. Si vous avez des idées sur la manière de le faire rapidement (200Hz) dans Matlab en temps réel pour une grille avec ~ 1k points de données utilisant 38 fonctions de péché superposées, j'aimerais l'entendre.


@CodenoOB L'astuce la plus évidente consiste uniquement à évaluer les fonctions de Trig à T0, puis pour T1, T2, etc., utilisez la formule d'addition. De cette façon, vous juste pour FP multiplier / ajouter et pas de trigle.


@CodenoOB Vous pouvez obtenir les 38 composants d'ondes sinusoïdales de Matlab et sur les calculs d'élévation d'onde dans votre code C / C ++. 38 n'est pas très nombreux, nous faisons régulièrement des centaines voire des milliers.


Expliquez pourquoi le voisin de (120x33) est (100x33)? En outre, si vous propagez une vague autour et que vous avez une limite, vous aurez besoin de faire un amortissement très compliqué sur les bords, ou vous obtiendrez des réflexions bizarres.


@David: Je ne suis pas tout à fait sûr de ce que vous entendez par "Just FP Multiple / Add", s'il vous plaît pourriez-vous élaborer un peu. @DOV: Je viens de saturer chaque coordonnée dans sa dimension. De cette façon, je n'aurai aucun arde discontinu perceptible. Le modèle de vague est basé sur certaines fonctions de Trig, je ne fais aucune théorie de la CFD "réaliste" où les vagues refléteraient et réfléchiraient des bords.


@CODENOOB: Ajout Formulas: Sin (x + Y) = sin (x) cos (y) + sin (y) cos (x) et ainsi de suite. Chaque composant d'élévation des vagues sera de la forme A sin (oméga t-phi) où T est le temps. En supposant que vous avez des intervalles de temps égaux, vous pouvez utiliser les formules d'addition pour transformer l'évaluation de la trigie très coûteuse dans le beaucoup plus rapidement (ordre de grandeur typiquement) FP multiplier / ajouter.


5 Réponses :


1
votes

min et max non?

x = std::min(100,x);
y = std::min(40,y);


1 commentaires

C'est mis en œuvre en termes de si l'opérateur conditionnel par défaut.



9
votes
template<typename T>
T saturate(T val, T min, T max) {
    return std::min(std::max(val, min), max);
}

1 commentaires

Ne fonctionnera pas si le Val a déjà souffert sous / débordement du type fondamental T.



4
votes

4 commentaires

MMX intrinsics Link est mort


@ERICJOHNSON: Cela ne devrait pas être une surprise puisque le poteau est de> 6 ans. Je ne suis pas sur le point de maintenir des liens dans plus de 2000 réponses postées! Les termes clés nécessaires à la recherche de MSDN ou de Google ont été fournis. Documentation archivée pour vs2010 ici , et Pour vs2015 ici - bien que ce n'est plus bien classé. J'imagine en 2017 aussi.


_sat _accum / _sat _fract Les types de point fixe ne sont pas pris en charge par GCC pour X86, Bras, Arm64 ou AVR. goodbolt.org/z/rrmma8l :( Je n'ai pas essayé d'autres Isas sur Godbolt, mais je Supposons que MIPS / POWERPC / RISC-V n'a pas de support de GCC non plus. GCC. gnu.org/onlinedocs/gcc/fixed-point.html ne dit pas quelles cibles sont supportées.


Oh, Clang les supporte avec -ffixed-point ! Mais pour X86, il suffit d'ajouter sans saturation réelle, juste en enveloppant. goodbolt.org/z/akwv0n . Mais pour RISC-V, il y a beaucoup d'instructions qui font ... quelque chose (?)



0
votes

ou si vous aimez compliqué de définir!

#define DERIVE_MAX (100)

//Saturate X at +/-DERIVE_MAX
#define SAT(x) ( ((x) > DERIVE_MAX) ? DERIVE_MAX : ( (-(x) > DERIVE_MAX) ? (-DERIVE_MAX) : (x) ) )


0 commentaires

9
votes

Et maintenant il y a, sous la forme de std :: pince . Et je suis à peine sept ans de retard :)


0 commentaires