Ez a feladat kicsit különbözik a többitől, ugyanis most egy új dolgot kell csinálni. Ilyen még nem volt az órán se. Amit szeretnénk, ha lenne egy a matematikai függvényeket magába foglaló osztály. Több okból: Egyrészt: például ha megpróbáljátok használni a cmath headerben lévő abs() függvényt a vektor abs() függvényében, akkor látni fogjátok, hogy így kell csinálni: ::abs(x);, ami nyilván nem ideális. Sőt, így elég lesz egy header filet include-olni a programban, ha például tangens függvényre van szükség, nem kell mindenhol megkeresni a neten, hogy hol van. (Elképzelhető az is, hogy egy bizonyos függvényt máshogy kell elérni más platformokon, így ez a választó kód is csak egyszer fog előfordulni.) Alapból jelenleg így tudnánk ezt az osztályt megcsinálni: class Math { public: float atan2(float a, float b) { return ::atan2(a, b); } //etc }; És így kellene használni: int main() { Math m; float t = m.atan2(1.32, 33.41); return 0; } Nyilván, itt fölöslegesen hozunk létre egy objektumot, mert nincsenek belső változói. Szerencsére van erre megoldás, méghozzá a statikus függvények: class Math { public: static float atan2(float a, float b) { return ::atan2(a, b); } //etc }; int main() { float t = Math::atan2(1.32, 33.41); return 0; } Látni, hogy nincs szükség létrehozni Math objektumot, a függvény meghívható csak így önmagában. Úgy érdemes rá gondolni, mintha egy "Math::atan2" nevű globális függvényt hoznánk létre. (Annyi a +, hogy ha van statikusnak megjelölt változó az osztályban, akkor azt is el lehet belőle érni, a normál változókat nem. -> Nem érhető el bennük a this pointer se.) Így kell őket 2 fájlra szétszedni: math.h: class Math { public: static float atan2(float a, float b); }; math.cpp: //nem kell a static szó a cpp fájlba! float Math::atan2(float a, float b) { return ::atan2(a, b); } Akkor a feladatok: 1. Írd meg az alábbi segédosztályt: Az includeok: #include , #include , #include , #include Defineok a header tetejére (Includeok utánra szokás rakni): #define MATH_PI 3.1415926535897932384626433833 #define EPSILON 0.00001 UML: |------------------------------------------------------------| | class Math | |------------------------------------------------------------| | | | + uint64_t RANDOM_32BIT_MAX; { static, const } | -> static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF; | | | + sin(x : float) : float { static } | -> return ::sinf(x); | + sin(x : double) : double { static } | -> return ::sin(x); | + cos(x : float) : float { static } | -> return ::cosf(x); | + cos(x : double) : double { static } | -> return ::cos(x); | + tan(x : float) : float { static } | -> return ::tanf(x); | + tan(x : double) : double { static } | -> return ::tan(x); | | | + asin(x : float) : float { static } | -> return ::asinf(x); | + asin(x : double) : double { static } | -> return ::asin(x); | + acos(x : float) : float { static } | -> return ::acosf(x); | + acos(x : double) : double { static } | -> return ::acos(x); | + atan(x : float) : float { static } | -> return ::atanf(x); | + atan(x : double) : double { static } | -> return ::atan(x); | + atan2(x : float, y : float) : float { static } | -> return ::atan2f(x, y); | + atan2(x : double, y : double) : double { static } | -> return ::atan2(x, y); | | | + sqrt(x : float) : float { static } | -> return ::sqrtf(x); | + sqrt(x : double) : double { static } | -> return ::sqrt(x); | + fmod(x : float, y : float) : float { static } | -> return ::fmodf(x, y); | + fmod(x : double, y : float) : double { static } | -> return ::fmod(x, y); | + floor(x : float) : float { static } | -> return ::floorf(x); | + floor(x : double) : double { static } | -> return ::floor(x); | + ceil(x : float) : float { static } | -> return ::ceilf(x); | + ceil(x : double) : double { static } | -> return ::ceil(x); | + pow(x : float, y : float) : float { static } | -> return ::powf(x, y); | + pow(x : double, y : float) : double { static } | -> return ::pow(x, y); | + log(x : float) : float { static } | -> return ::logf(x); | + log(x : double) : double { static } | -> return ::log(x); | | | + inv_sqrt(x : float) : float { static } | -> return (float)(1.0 / ::sqrtf(x)); | + fast_inv_sqrt(number : float) : float { static } | -> Implementáció lejjebb | | | + abs(x : float) : float { static } | -> return x > 0 ? x : -x; | + abs(x : double) : double { static } | -> return x > 0 ? x : -x; | + abs(x : int) : int { static } | -> return x > 0 ? x : -x; | | | + deg2rad(x : float) : float { static } | -> return x * MATH_PI / 180.0; | + deg2rad(x : double) : double { static } | -> return x * MATH_PI / 180.0; | + deg2rad(x : int) : int { static } | -> return x * MATH_PI / 180.0; | | | + rad2deg(x : float) : float { static } | -> return x * 180.0 / MATH_PI; | + rad2deg(x : double) : double { static } | -> return x * 180.0 / MATH_PI; | + rad2deg(x : int) : int { static } | -> return x * 180.0 / MATH_PI; | | | + is_equal_approx(a : float, b : float) : bool { static } | -> mint vektorban | + is_zero_approx(a : float) : bool { static } | | | | + seed(s : unsigned int) { static } | -> srand(s); | + randomize() { static } | -> srand(time(NULL)); | | | + rand() : int { static } | -> return ::rand(); | + randf() : float { static } | -> return ::rand() / static_cast(RANDOM_32BIT_MAX); | + randd() : double { static } | -> return ::rand() / static_cast(RANDOM_32BIT_MAX); | | | + rand(int m) : int { static } | -> return rand() % m; | | | + rand(from : int, to : int) : int { static } | -> return (rand() % (to - from)) + from; | + rand(from : float, to : float) : float { static } | -> return randf() * (to - from) + from; | + rand(from : double, to : double) : double { static } | -> return randd() * (to - from) + from; |------------------------------------------------------------| fast_inv_sqrt: float fast_inv_sqrt(float number) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * ( long * ) &y; i = 0x5f3759df - ( i >> 1 ); y = * ( float * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); return y; } Note: Ez az algoritmus a Quake 3 forráskódjában talált implementációja miatt híresült el. Érdekességnek raktam bele, ha bármi probléma van vele, hagyjátok ki. Érdemes megnézni a matematikai hátterét (pl a youtube vid, vagy a wikipédia cikk első pár paragrafusa)! Wikipédia: https://en.wikipedia.org/wiki/Fast_inverse_square_root Youtube vid: Nemean elmagyarázza, hogy hogyan is működik: https://www.youtube.com/watch?v=p8u_k2LIZyo - Fast Inverse Square Root — A Quake III Algorithm Stack overflow: https://stackoverflow.com/questions/1349542/john-carmacks-unusual-fast-inverse-square-root-quake-iii 64 bitre (double-hoz): https://stackoverflow.com/questions/11644441/fast-inverse-square-root-on-x64#11644533 Egyéb megj: Ezek a random (ranf, randd) függvények nem a leggyorsabbak, nagyon sokat lehet rajtuk gyorsítani alapszinű /low level/ hardwares ismeretekkel, és matematikával. Akit érdekel érdemes kürölnézni nagyobb projektekben, hogy hogy vannak ilyenek implementálva. 2. Most, hogy már kész a Math osztályod, menj visza a Vector2, Vector3, és Rect2 osztályokba, nézd végig a függvényeiket, és cserélj le mindent amit lehet, Math osztálybelire.