/* ////////////////////////////////////////////////////// // SNDREAL.CXX - Librairie SOUNDxd version 2.0 // ////////////////////////////////////////////////////// // Fonctions de gestion des pseudo-reels // ////////////////////////////////////////////////////// */ #include "SND\snddef.h" #include "SNDinc.h" #ifdef U64 #include #else #ifdef PSX #include #include #else #include #endif #endif #include "sndvect.h" /*---------------------------------------------------------*/ /* MulRealRealSnd: multiplication exacte de 2 SndReal*/ /* Entrees:r1,r2=reels à multiplier*/ /* Sortie:resultat (r1*r2)*/ /*--------------------------------------------------------*/ SndReal SND_CALL SND_fn_rMulRealRealSnd(SndReal r1,SndReal r2) { unsigned long r1p,r2p,t1,t2,t3,t4,r3p; r1p=abs(r1); r2p=abs(r2); if ((r1p<0x800) && (r2p<0x800) && (r1p>0xFF) && (r2p>0xFF)) return ((r1>>8)*(r2>>8)); if (r1p<0x7F) return ((r1 * (r2>>8))>>8); if (r2p<0x7F) return ((r2 * (r1>>8))>>8); t1=(r1p & 0xFFFF) * (r2p & 0xFFFF); t2=(r1p & 0xFFFF) * (r2p>>16); t3=(r1p>>16) * (r2p & 0xFFFF); t4=(r1p>>16) * (r2p >>16); r3p=(t1>>16)+t2+t3+(t4<<16); if ((r1<0)^(r2<0)) return (SndReal)(0-r3p); else return (SndReal)r3p; } /*---------------------------------------------------------*/ /* MulRealRealQuickSnd: multiplication rapide de 2 SndReal*/ /* Entrees:r1,r2=reels à multiplier*/ /* Sortie:resultat (r1*r2)*/ /* Valide ssi -abs(ri)>0x800; octet de poid faible non valide*/ /*--------------------------------------------------------*/ SndReal SND_CALL SND_fn_rMulRealRealQuickSnd(SndReal r1,SndReal r2) { return ((r1>>8)*(r2>>8)); } /*---------------------------------------------------------*/ /* SqrtRealSnd: racine carre d'un SndReal*/ /* Entrees:r dont il faut extraire la racine*/ /* Sortie:racine carre de r*/ /*--------------------------------------------------------*/ SndReal SND_CALL SND_fn_rSqrtRealSnd(SndReal r) { #ifdef U64 return M_DoubleToRealSnd(sqrtf(M_RealToDoubleSnd(r))); #else #ifdef PSX return M_DoubleToRealSnd(csqrt(M_RealToDoubleSnd(r))); #else return M_DoubleToRealSnd(sqrt(M_RealToDoubleSnd(r))); #endif #endif } /*---------------------------------------------------------*/ /* DivRealRealSnd: division d'un SndReal par un autre SndReal*/ /* avec peut de precision (1/65000 à 1/256)*/ /* Entrees:r1=dividente*/ /* r2=diviseur*/ /* Sortie:resultat de r1/r2*/ /*--------------------------------------------------------*/ SndReal SND_CALL SND_fn_rDivRealRealQuickSnd(SndReal r1,SndReal r2) { /*il faut retourner 2^16*r1/r2, c.a.d.*/ /* r1 !0 7f !80 !8000 !800000 */ /*r2 ! ! ! ! */ /*------+----------------------------------------*/ /*0 7f ! r1<<16 ! ? !r2>>16 */ /*80 ! . . !r1<<8 !.*/ /*8000 ! . . !r1<<8 !.*/ /*800000! . . !r1<<8 !.*/ if (SND_fn_rAbsRealSnd(r1)<0x8000) {/*r1 suffisament petit*/ snd_assert(r2); /*r2 null -> division by zero*/ return ((r1<<16)/r2); } if (SND_fn_rAbsRealSnd(r1)<0x800000) {/*r1 moyen*/ snd_assert(r2>>8);/* trop grand e=ecart entre r1 et r2*/ return ((r1<<8)/(r2>>8)); } /*r1 grand*/ if (SND_fn_rAbsRealSnd(r2)>0x8000) {/*r2 grand*/ snd_assert(r2>>8); return ((r1/(r2>>8))<<8); } /*vaillle que vaille*/ snd_assert(r2); return (r1/r2)<<16; } /*---------------------------------------------------------*/ /* DivRealRealSnd: division d'un SndReal par un autre SndReal*/ /* avec precision */ /* Entrees:r1=dividente*/ /* r2=diviseur*/ /* Sortie:resultat de r1/r2*/ /*--------------------------------------------------------*/ SndReal SND_CALL SND_fn_rDivRealRealSnd(SndReal r1,SndReal r2) { #ifdef PSX return SND_fn_rDivRealRealQuickSnd(r1,r2); #else /*il faut retourner 2^16*r1/r2, c.a.d.*/ return M_DoubleToRealSnd( (float)r1 /(float)r2); #endif } /*-----------------------------------*/ /* Valeur absolu*/ /*-----------------------------------*/ SndReal SND_CALL SND_fn_rAbsRealSnd(SndReal r) { return abs(r); } /*------------------------------------------------*/ /* Calcul rapide et approche de sqrt(a^2+b^2+c^2)*/ /*------------------------------------------------*/ SndReal SND_CALL SND_fn_rPseudoNormeRealSnd(SndReal r1,SndReal r2,SndReal r3) { SndVector v; v.x=r1; v.y=r2; v.z=r3; return SND_fn_rPseudoNormeVectorSnd(&v); } void SND_CALL SND_fn_vSndRealTwinToSndReal(SndRealTwin rtwin,SndReal* pr1,SndReal* pr2) { if (pr1) *pr1=(rtwin>>16)<<8; if (pr2) *pr2=(rtwin<<16)>>8; } SndRealTwin SND_CALL SND_fn_rtSndRealToSndRealTwin(SndReal r1,SndReal r2) { snd_assert(r1>8)&0xFFFF); }