X-Git-Url: http://git.euphorik.ch/?p=GPU.git;a=blobdiff_plain;f=WCudaMSE%2FStudent_Cuda_Image%2Fsrc%2Fcpp%2Fcore%2F03_Newton%2Fmoo%2Fdevice%2Fmath%2FNewtonMath.h;h=3c7617047a51c656f33be852ff266d24a2ee84be;hp=5edf6ee56c9671932ce96e06df12cac2c9bf336e;hb=2d95edd9a2d09421e5eae56755bdf3105e12edf7;hpb=19015d26dfb874d075516772ef531ee5e42fa213 diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/03_Newton/moo/device/math/NewtonMath.h b/WCudaMSE/Student_Cuda_Image/src/cpp/core/03_Newton/moo/device/math/NewtonMath.h index 5edf6ee..3c76170 100755 --- a/WCudaMSE/Student_Cuda_Image/src/cpp/core/03_Newton/moo/device/math/NewtonMath.h +++ b/WCudaMSE/Student_Cuda_Image/src/cpp/core/03_Newton/moo/device/math/NewtonMath.h @@ -2,44 +2,142 @@ #define NEWTON_MATH_H_ #include +#include +#include -#include "CalibreurF.h" #include "ColorTools.h" class NewtonMath { + enum Solution { + A, // (1 0) + B, // (-1/2 sqrt(3)/2) + C // (-1/2 -sqrt(3)/2) + }; + + /* + * Renvoie la valeur (x1, x2) de l'itération suivante (i+1). + */ + __device__ + static void nextX(float x1, float x2, float& x1_next, float& x2_next) + { + float f_x1 = powf(x1, 3.0) - 3.0 * x1 * powf(x2, 2.0) - 1.0; + float f_x2 = powf(x2, 3.0) - 3.0 * powf(x1, 2.0) * x2; + + // La matrice est représentée comme cela : + // a b + // c d + float jacobienne_f_x_a = 3.0 * powf(x1, 2.0) - 3.0 * powf(x2, 2.0); + float jacobienne_f_x_b = -6.0 * x1 * x2; + float jacobienne_f_x_c = -6.0 * x1 * x2; + float jacobienne_f_x_d = -3.0 * powf(x1, 2.0) + 3.0 * powf(x2, 2.0); + + float det_inverse_jacobienne = 1.0 / (jacobienne_f_x_a * jacobienne_f_x_d - jacobienne_f_x_b * jacobienne_f_x_c); + float jacobienne_f_x_a_inverse = jacobienne_f_x_d * det_inverse_jacobienne; + float jacobienne_f_x_b_inverse = -jacobienne_f_x_b * det_inverse_jacobienne; + float jacobienne_f_x_c_inverse = -jacobienne_f_x_c * det_inverse_jacobienne; + float jacobienne_f_x_d_inverse = jacobienne_f_x_a * det_inverse_jacobienne; + + x1_next = x1 - (jacobienne_f_x_a_inverse * f_x1 + jacobienne_f_x_b_inverse * f_x2); + x2_next = x2 - (jacobienne_f_x_c_inverse * f_x1 + jacobienne_f_x_d_inverse * f_x2); + } + + /* + * Renvoie la distance entre deux vecteurs a et b. + */ + __device__ + static float distance_carre(float a1, float a2, float b1, float b2) + { + return powf(a1 - b1, 2.0) + powf(a2 - b2, 2.0); + } + + __device__ + static float distance(float a1, float a2, float b1, float b2) + { + return (powf(a1 - b1, 2.0) + powf(a2 - b2, 2.0)) / (powf(b1, 2.0) + powf(b2, 2.0)); + } + public: + /* + * n est le nombre d'iteration. + */ __device__ - NewtonMath() - : calibreur(IntervalF(1, 100), IntervalF(0, 1)) + NewtonMath(int n = 1000) + : n(n) { } __device__ virtual ~NewtonMath() {} - public: - /** - * x=pixelI - * y=pixelJ - */ __device__ - void colorXY(uchar4* ptrColor, float x, float y) const + void colorXY(uchar4* ptrColor, float x1, float x2) const { - ptrColor->x = 0; - ptrColor->y = 0; - ptrColor->z = 0; - - int i = 0; - float s = static_cast(i); - this->calibreur.calibrer(s); - ColorTools::HSB_TO_RVB(s, ptrColor); - } + const float A1 = 1.0; + const float A2 = 0.0; + const float B1 = -1.0 / 2.0; + const float B2 = sqrt(3.0) / 2.0; + const float C1 = -1.0 / 2.0; + const float C2 = -sqrt(3.0) / 2.0; - private: + const float epsilon = 0.001; + + float nearest_current_solution_distance = FLT_MAX; + Solution nearest_current_solution = A; + + for (int i = 0; i < this->n; i++) + { + float distance_to_A = distance(x1, x2, A1, A2); + float distance_to_B = distance(x1, x2, B1, B2); + float distance_to_C = distance(x1, x2, C1, C2); + + if (distance_to_A < nearest_current_solution_distance && distance_to_A < distance_to_B && distance_to_A < distance_to_C) + { + nearest_current_solution = A; + nearest_current_solution_distance = distance_to_A; + } + else if (distance_to_B < nearest_current_solution_distance && distance_to_B < distance_to_A && distance_to_B < distance_to_C) + { + nearest_current_solution = B; + nearest_current_solution_distance = distance_to_B; + } + else if (distance_to_C < nearest_current_solution_distance && distance_to_C < distance_to_A && distance_to_C < distance_to_B) + { + nearest_current_solution = C; + nearest_current_solution_distance = distance_to_C; + } + + if (nearest_current_solution_distance < epsilon) + break; + + nextX(x1, x2, x1, x2); + } + + switch (nearest_current_solution) + { + // Noir. + case A : + ptrColor->x = 0; + ptrColor->y = 0; + ptrColor->z = 0; + break; + // Gris. + case B : + ptrColor->x = 128; + ptrColor->y = 128; + ptrColor->z = 128; + break; + // Blanc. + case C : + ptrColor->x = 255; + ptrColor->y = 255; + ptrColor->z = 255; + break; + } + } private: - CalibreurF calibreur; + int n; }; #endif