From 2d3a9a6eb682660b7c3f342c3d7975da1e0a1bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20El=20Kharroubi?= <michael.el-kharroubi@hesge.ch> Date: Sun, 10 Oct 2021 20:11:18 +0200 Subject: [PATCH] Ajout du tp_vec2 --- Makefile | 4 + practical_work/Makefile | 29 +++ practical_work/MathJax.js | 4 + practical_work/tp_vec.md | 55 +++++ practical_work/tp_vec2/Makefile | 24 ++ practical_work/tp_vec2/gfx/gfx.c | 105 ++++++++ practical_work/tp_vec2/gfx/gfx.h | 41 ++++ practical_work/tp_vec2/main.c | 54 +++++ practical_work/tp_vec2/vec2/vec2.c | 74 ++++++ practical_work/tp_vec2/vec2/vec2.h | 41 ++++ practical_work/tp_vec2/vec2/vec_tests.c | 309 ++++++++++++++++++++++++ 11 files changed, 740 insertions(+) create mode 100644 practical_work/Makefile create mode 100644 practical_work/MathJax.js create mode 100644 practical_work/tp_vec.md create mode 100644 practical_work/tp_vec2/Makefile create mode 100644 practical_work/tp_vec2/gfx/gfx.c create mode 100644 practical_work/tp_vec2/gfx/gfx.h create mode 100644 practical_work/tp_vec2/main.c create mode 100644 practical_work/tp_vec2/vec2/vec2.c create mode 100644 practical_work/tp_vec2/vec2/vec2.h create mode 100644 practical_work/tp_vec2/vec2/vec_tests.c diff --git a/Makefile b/Makefile index 2bf36f8..ed04ce3 100644 --- a/Makefile +++ b/Makefile @@ -61,9 +61,13 @@ deploy: all cp cours.html phys/index.html cp cours.pdf phys/cours.pdf make -C exercices + make -C practical_work mkdir -p phys/exercices cp exercices/*.html phys/exercices cp exercices/*.pdf phys/exercices + mkdir -p phys/practical_work + cp practical_work/*.html phys/practical_work + cp practical_work/*.pdf phys/practical_work clean: rm -f *.html *.pdf $(MARKDOWN) $(PDF) $(TEX) $(HTML) diff --git a/practical_work/Makefile b/practical_work/Makefile new file mode 100644 index 0000000..bb87bf8 --- /dev/null +++ b/practical_work/Makefile @@ -0,0 +1,29 @@ +OPTIONS = --filter=pandoc-numbering +OPTIONS += --filter=pandoc-crossref + +PDFOPTIONS = --highlight-style kate +PDFOPTIONS += --pdf-engine pdflatex +PDFOPTIONS += --number-sections +PDFOPTIONS += --template=./default.latex + +HTMLOPTIONS += -t html5 +HTMLOPTIONS += -c ../css/tufte-css/tufte.css +HTMLOPTIONS += --self-contained +HTMLOPTIONS += --mathjax=MathJax.js + +MD=$(wildcard *.md) +HTML=$(MD:%.md=%.html) +PDF=$(MD:%.md=%.pdf) + + +all: $(HTML) $(PDF) + +%.pdf: %.md Makefile + pandoc -s $(OPTIONS) $(PDFOPTIONS) -o $@ $< + +%.html: %.md Makefile + pandoc -s $(OPTIONS) $(HTMLOPTIONS) -o $@ $< + +clean: + rm -rf *.html *.pdf + diff --git a/practical_work/MathJax.js b/practical_work/MathJax.js new file mode 100644 index 0000000..3c5458c --- /dev/null +++ b/practical_work/MathJax.js @@ -0,0 +1,4 @@ +var fileref=document.createElement('script') +fileref.setAttribute("type","text/javascript") +fileref.setAttribute("src", "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML") +document.getElementsByTagName("head")[0].appendChild(fileref) diff --git a/practical_work/tp_vec.md b/practical_work/tp_vec.md new file mode 100644 index 0000000..e2c4a9a --- /dev/null +++ b/practical_work/tp_vec.md @@ -0,0 +1,55 @@ +--- +# author: +# - El Kharroubi Michaël +title: "Travail pratique : implémentation des vecteurs en deux dimensions en C" +autoSectionLabels: true +autoEqnLabels: false +eqnPrefix: + - "éq." + - "éqs." +chapters: true +numberSections: false +chaptersDepth: 1 +sectionsDepth: 3 +lang: fr +documentclass: article +papersize: A4 +cref: false +pandoc-numbering: + - category: exercice +urlcolor: blue +--- + +# But + +- Rappel sur les opérations vectorielles de base en deux dimensions. +- Implémenter une librairie en C, qui pourra être réutilisée par la suite. + +# Énoncé + +Dans le cadre de ce travail pratique, vous serez amené à compléter le code fourni, afin de satisfaire l'ensemble des tests. Vous pouvez retrouver les formules nécessaires, ainsi qu'un rappel théorique sur le site du cours [malaspinas.academy/phys](http://malaspinas.academy/phys/index.html#vecteurs). Si la formule pour l'une des fonctions ne se trouve pas dans le cours, c'est à vous de trouver la solution. + +Joint à cet énoncé, vous trouverez un dossier nommé `tp_vec2` sur **\textcolor{red}{(À compléter par tes soins)}**. Ce dossier contient les fichiers suivants : + +``` +tp_vec2 +|-- gfx # Librairie graphique simple gfx +| |-- gfx.c +| |-- gfx.h +|-- main.c #Exemple d'utilisation de la librairie gfx & vec2 +|-- Makefile +|-- vec2 # Librairie vecteurs 2d + |-- vec2.c # Fichier à compléter + |-- vec2.h + |-- vec_tests.c # Programme de test +``` + +Le fichier `vec2.c` contient 12 fonctions à compléter. Deux d'entre elles le sont déjà. Chaque fonction possède un entête et une signature, vous devez la compléter en les respectant. **Attention**, vous **ne devez pas** modifier la signature des fonctions (nom et arguments). + +Le travail pratique est terminé, lorsque que l'ensemble des tests passent. Vous pouvez exécuter les tests à tout moment en effectuant la commande `make run_tests` dans le répertoire `tp_vec2`. + +Une fois que tous les tests passent avec succès, vous pouvez parcourir le fichier `main.c`. Essayez de comprendre ce qui y est fait. Dans un second temps, commencez par installer la librairie SDL2 (`libsdl2-dev` sur ubuntu). Puis, exécutez la commande `make main`, suivie de `./main` afin d'afficher le résultat. + +# Travail à rendre + +**\textcolor{red}{(À compléter par tes soins)}** \ No newline at end of file diff --git a/practical_work/tp_vec2/Makefile b/practical_work/tp_vec2/Makefile new file mode 100644 index 0000000..a03093a --- /dev/null +++ b/practical_work/tp_vec2/Makefile @@ -0,0 +1,24 @@ +#The compiler +CC:=gcc +#The flags passed to the compiler +CFLAGS:=-g -O3 -Wall -Wextra -fsanitize=address -fsanitize=leak -std=gnu11 +#The flags passed to the linker +LDFLAGS:=-lm -lSDL2 +#Path to the lib Vec2 +VPATH:=vec2 gfx + +run_tests: tests + ./$< + +main: main.o vec2.o gfx.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +tests: vec_tests.o vec2.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +vec2.o: vec2.h + +gfx.o: gfx.h + +clean: + rm -f *.o main tests diff --git a/practical_work/tp_vec2/gfx/gfx.c b/practical_work/tp_vec2/gfx/gfx.c new file mode 100644 index 0000000..cd6662f --- /dev/null +++ b/practical_work/tp_vec2/gfx/gfx.c @@ -0,0 +1,105 @@ +/// @file gfx.c +/// @author Florent Gluck +/// @date November 6, 2016 +/// Helper routines to render pixels in fullscreen graphic mode. +/// Uses the SDL2 library. + +#include "gfx.h" +#include <assert.h> + +/// Create a fullscreen graphic window. +/// @param title Title of the window. +/// @param width Width of the window in pixels. +/// @param height Height of the window in pixels. +/// @return a pointer to the graphic context or NULL if it failed. +struct gfx_context_t *gfx_create(char *title, uint32_t width, uint32_t height) +{ + if (SDL_Init(SDL_INIT_VIDEO) != 0) + goto error; + SDL_Window *window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_RESIZABLE); + SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); + SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, width, height); + uint32_t *pixels = malloc(width * height * sizeof(uint32_t)); + struct gfx_context_t *ctxt = malloc(sizeof(struct gfx_context_t)); + + if (!window || !renderer || !texture || !pixels || !ctxt) + goto error; + + ctxt->renderer = renderer; + ctxt->texture = texture; + ctxt->window = window; + ctxt->width = width; + ctxt->height = height; + ctxt->pixels = pixels; + + SDL_ShowCursor(SDL_DISABLE); + gfx_clear(ctxt, COLOR_BLACK); + return ctxt; + +error: + return NULL; +} + +/// Draw a pixel in the specified graphic context. +/// @param ctxt Graphic context where the pixel is to be drawn. +/// @param column X coordinate of the pixel. +/// @param row Y coordinate of the pixel. +/// @param color Color of the pixel. +void gfx_putpixel(struct gfx_context_t *ctxt, uint32_t column, uint32_t row, uint32_t color) +{ + if (column < ctxt->width && row < ctxt->height) + ctxt->pixels[ctxt->width * row + column] = color; +} + +/// Clear the specified graphic context. +/// @param ctxt Graphic context to clear. +/// @param color Color to use. +void gfx_clear(struct gfx_context_t *ctxt, uint32_t color) +{ + int n = ctxt->width * ctxt->height; + while (n) + ctxt->pixels[--n] = color; +} + +/// Display the graphic context. +/// @param ctxt Graphic context to clear. +void gfx_present(struct gfx_context_t *ctxt) +{ + SDL_UpdateTexture( + ctxt->texture, NULL, ctxt->pixels, ctxt->width * sizeof(uint32_t)); + SDL_RenderCopy(ctxt->renderer, ctxt->texture, NULL, NULL); + SDL_RenderPresent(ctxt->renderer); +} + +/// Destroy a graphic window. +/// @param ctxt Graphic context of the window to close. +void gfx_destroy(struct gfx_context_t *ctxt) +{ + SDL_ShowCursor(SDL_ENABLE); + SDL_DestroyTexture(ctxt->texture); + SDL_DestroyRenderer(ctxt->renderer); + SDL_DestroyWindow(ctxt->window); + free(ctxt->pixels); + ctxt->texture = NULL; + ctxt->renderer = NULL; + ctxt->window = NULL; + ctxt->pixels = NULL; + SDL_Quit(); + free(ctxt); +} + +/// If a key was pressed, returns its key code (non blocking call). +/// List of key codes: https://wiki.libsdl.org/SDL_Keycode +/// @return the key that was pressed or 0 if none was pressed. +SDL_Keycode gfx_keypressed() +{ + SDL_Event event; + if (SDL_PollEvent(&event)) + { + if (event.type == SDL_KEYDOWN) + return event.key.keysym.sym; + } + return 0; +} \ No newline at end of file diff --git a/practical_work/tp_vec2/gfx/gfx.h b/practical_work/tp_vec2/gfx/gfx.h new file mode 100644 index 0000000..45b91d8 --- /dev/null +++ b/practical_work/tp_vec2/gfx/gfx.h @@ -0,0 +1,41 @@ +#ifndef _GFX_H_ +#define _GFX_H_ + +#include "vec2/vec2.h" +#include <SDL2/SDL.h> +#include <stdbool.h> +#include <stdint.h> + +#define MAKE_COLOR(r, g, b) \ + ((uint32_t)b | ((uint32_t)g << 8) | ((uint32_t)r << 16)) + +#define COLOR_GET_B(color) (color & 0xff) +#define COLOR_GET_G(color) ((color >> 8) & 0xff) +#define COLOR_GET_R(color) ((color >> 16) & 0xff) + +#define COLOR_BLACK 0x00000000 +#define COLOR_RED 0x00FF0000 +#define COLOR_GREEN 0x0000FF00 +#define COLOR_BLUE 0x000000FF +#define COLOR_WHITE 0x00FFFFFF +#define COLOR_YELLOW 0x00FFFF00 + +struct gfx_context_t +{ + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; + uint32_t *pixels; + uint32_t width; + uint32_t height; +}; + +extern void gfx_putpixel( + struct gfx_context_t *ctxt, uint32_t column, uint32_t row, uint32_t color); +extern void gfx_clear(struct gfx_context_t *ctxt, uint32_t color); +extern struct gfx_context_t *gfx_create(char *text, uint32_t width, uint32_t height); +extern void gfx_destroy(struct gfx_context_t *ctxt); +extern void gfx_present(struct gfx_context_t *ctxt); +extern SDL_Keycode gfx_keypressed(); + +#endif diff --git a/practical_work/tp_vec2/main.c b/practical_work/tp_vec2/main.c new file mode 100644 index 0000000..ac27974 --- /dev/null +++ b/practical_work/tp_vec2/main.c @@ -0,0 +1,54 @@ +#include "gfx/gfx.h" +#include "vec2/vec2.h" +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#define SCREEN_WIDTH 1280 +#define SCREEN_HEIGHT 720 + +double rand_dbl() +{ + return ((double)rand()) / RAND_MAX; +} + +int main() +{ + srand(time(NULL)); + struct gfx_context_t *ctxt = + gfx_create("Vec2 demo", SCREEN_WIDTH, SCREEN_HEIGHT); + if (!ctxt) + { + fprintf(stderr, "Graphics initialization failed!\n"); + return EXIT_FAILURE; + } + + vec2 center = vec2_create(0.5, 0.5); + double radius = 0.5; + for (int i = 0; i < 250000; i++) + { + + vec2 r = vec2_create(rand_dbl(), rand_dbl()); + + //Draw pixel if in circle + if (vec2_norm(vec2_sub(r, center)) < radius) + { + coordinates pixel = vec2_to_coordinates(r, SCREEN_WIDTH, SCREEN_HEIGHT); + //Random color (not black) + uint32_t color = rand() % 0xFFFFFF; + + gfx_putpixel(ctxt, pixel.column, pixel.row, color); + } + } + + gfx_present(ctxt); + while (true) + { + if (gfx_keypressed() == SDLK_ESCAPE) + { + break; + } + } + gfx_destroy(ctxt); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/practical_work/tp_vec2/vec2/vec2.c b/practical_work/tp_vec2/vec2/vec2.c new file mode 100644 index 0000000..ad16ee4 --- /dev/null +++ b/practical_work/tp_vec2/vec2/vec2.c @@ -0,0 +1,74 @@ +#include "vec2.h" +#include <math.h> +#include <stdio.h> + +/// Create a 2d vector. +/// @param x_ The first component. +/// @param y_ The second component. +/// @return The newly created vector. +vec2 vec2_create(double x_, double y_) {} + +/// Create a zero 2d vector. +/// @return The newly created zero vector. +vec2 vec2_create_zero() { vec2_create(0.0, 0.0); } + +/// Add two vectors. +/// @param lhs The left operand. +/// @param rhs The right operand. +/// @return The sum in a new vector. +vec2 vec2_add(vec2 lhs, vec2 rhs) {} + +/// Substract two vectors. +/// @param lhs The left operand. +/// @param rhs The right operand. +/// @return The difference in a new vector. +vec2 vec2_sub(vec2 lhs, vec2 rhs) {} + +/// Multiply a vector by a scalar. +/// @param scalar The left operand, a scalar. +/// @param rhs The right operand, a vector. +/// @return The product in a new vector. +vec2 vec2_mul(double scalar, vec2 rhs) {} + +/// Compute the dot product (scalar product) between two vectors. +/// @param lhs The left operand. +/// @param rhs The right operand. +/// @return The dot product. +double vec2_dot(vec2 lhs, vec2 rhs) {} + +/// Compute the square of the euclidean norm of a given vector. +/// @param v The vector. +/// @return The square of the norm. +double vec2_norm_sqr(vec2 v) {} + +/// Compute the euclidean norm of a given vector. +/// @param v The vector. +/// @return The norm. +double vec2_norm(vec2 v) {} + +/// Compute the normalization of a given vector. +/// @param v The vector. +/// @return The new normalized vector. +vec2 vec2_normalize(vec2 v) {} + +/// Check whether two vectors are approximately equals within a given tolerance. +/// @param lhs The left operand. +/// @param rhs The right operand. +/// @param eps The tolerance. +/// @return The dot product. +bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps) {} + +/// Compute the coordinates of a 2d vector (with components between 0 and 1) +/// in a given screen matrix. +/// @param v The 2d vector. +/// @param width The screen width. +/// @param height The screen height. +/// @return The coordinates (rwo, column). +coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height) {} + +/// Print a vector in the standard output. +/// @param v The vector. +void vec2_print(vec2 v) +{ + printf("x = %g, y = %g\n", v.x, v.y); +} \ No newline at end of file diff --git a/practical_work/tp_vec2/vec2/vec2.h b/practical_work/tp_vec2/vec2/vec2.h new file mode 100644 index 0000000..ed04035 --- /dev/null +++ b/practical_work/tp_vec2/vec2/vec2.h @@ -0,0 +1,41 @@ +#ifndef _VEC2_H_ +#define _VEC2_H_ + +#include <stdbool.h> +#include <stdint.h> + +typedef struct _vec2 +{ + double x, y; +} vec2; + +typedef struct _coordinates +{ + uint32_t row, column; +} coordinates; + +vec2 vec2_create(double x_, double y_); + +vec2 vec2_create_zero(); + +vec2 vec2_add(vec2 lhs, vec2 rhs); + +vec2 vec2_sub(vec2 lhs, vec2 rhs); + +vec2 vec2_mul(double scalar, vec2 rhs); + +double vec2_dot(vec2 lhs, vec2 rhs); + +double vec2_norm_sqr(vec2 v); + +double vec2_norm(vec2 v); + +vec2 vec2_normalize(vec2 v); + +bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps); + +coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height); + +void vec2_print(vec2 v); + +#endif diff --git a/practical_work/tp_vec2/vec2/vec_tests.c b/practical_work/tp_vec2/vec2/vec_tests.c new file mode 100644 index 0000000..91b32f5 --- /dev/null +++ b/practical_work/tp_vec2/vec2/vec_tests.c @@ -0,0 +1,309 @@ +#include "vec2.h" +#include <stdio.h> +#include <stdbool.h> +#include <math.h> + +typedef struct _test_result +{ + bool passed; + const char *name; +} test_result; + +typedef test_result (*unit_test_t)(void); + +void print_in_color(char *color, char *text) +{ + printf("\033%s", color); + printf("%s", text); + printf("\033[0m"); +} +void print_in_red(char *text) +{ + print_in_color("[0;31m", text); +} +void print_in_green(char *text) +{ + print_in_color("[0;32m", text); +} + +bool dbl_eq(double a, double b) +{ + return fabs(a - b) < 1e-6; +} + +/* +* +* Write your tests here +* +*/ +/* TODO +vec2 vec2_create(double x_, double y_); -- Ok +vec2 vec2_create_zero(); -- Ok +vec2 vec2_add(vec2 lhs, vec2 rhs); -- Ok +vec2 vec2_sub(vec2 lhs, vec2 rhs); -- Ok +vec2 vec2_mul(double scalar, vec2 lhs); -- Ok +double vec2_dot(vec2 lhs, vec2 rhs); -- Ok +double vec2_norm_sqr(vec2 v); -- Ok +double vec2_norm(vec2 v); -- Ok +vec2 vec2_normalize(vec2 v); -- Ok +bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps); +coordinates vec2_to_coordinates(vec2 v, uint32_t width, uint32_t height); +*/ +const double u_x[] = {1.25, 3.53, 2.64, 8.8}; +const double u_y[] = {3.42, 7.22, 5.32, 2.44}; +const double v_x[] = {4.32, 6.21, 7.42, 9.32}; +const double v_y[] = {5.22, 3.56, 8.65, 6.44}; +const uint32_t nb_tests = sizeof(u_x) / sizeof(double); + +test_result t_vec2_create_0() +{ + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 v = vec2_create(u_x[i], u_y[i]); + if (u_x[i] != v.x || u_y[i] != v.y) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_create 0"}; +} +test_result t_vec2_create_zero_0() +{ + vec2 v = vec2_create_zero(); + + return (test_result){.passed = (v.x == 0.0 && v.y == 0.0), + .name = "Test vec2_create_zero 0"}; +} +test_result t_vec2_add_0() +{ + double r_x[] = {5.57, 9.74, 10.06, 18.12}; + double r_y[] = {8.64, 10.78, 13.97, 8.88}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 u = vec2_create(u_x[i], u_y[i]); + vec2 v = vec2_create(v_x[i], v_y[i]); + vec2 r = vec2_add(u, v); + if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i]))) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_add 0"}; +} +test_result t_vec2_sub_0() +{ + double r_x[] = {-3.07, -2.68, -4.78, -0.52}; + double r_y[] = {-1.80, 3.66, -3.33, -4.00}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 u = vec2_create(u_x[i], u_y[i]); + vec2 v = vec2_create(v_x[i], v_y[i]); + vec2 r = vec2_sub(u, v); + if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i]))) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_sub 0"}; +} +test_result t_vec2_mul_0() +{ + double r_x[] = {5.40, 21.9213, 19.5888, 82.016}; + double r_y[] = {14.7744, 44.8362, 39.4744, 22.740800}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + double alpha = v_x[i]; + vec2 u = vec2_create(u_x[i], u_y[i]); + vec2 r = vec2_mul(alpha, u); + if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i]))) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_mul 0"}; +} +test_result t_vec2_dot_0() +{ + double r[] = {23.2524, 47.6245, 65.6068, 97.7296}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 u = vec2_create(u_x[i], u_y[i]); + vec2 v = vec2_create(v_x[i], v_y[i]); + double res = vec2_dot(u, v); + if (!dbl_eq(res, r[i])) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_dot 0"}; +} +test_result t_vec2_norm_sqr_0() +{ + double r[] = {13.2589, 64.5893, 35.272, 83.3936}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 u = vec2_create(u_x[i], u_y[i]); + double res = vec2_norm_sqr(u); + if (!dbl_eq(res, r[i])) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_norm_sqr 0"}; +} +test_result t_vec2_norm_0() +{ + double r[] = {3.641277, 8.036747, 5.939023, 9.132010}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 u = vec2_create(u_x[i], u_y[i]); + double res = vec2_norm(u); + if (!dbl_eq(res, r[i])) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_norm 0"}; +} +test_result t_vec2_normalize_0() +{ + double r_x[] = {0.343286, 0.439232, 0.444518, 0.963643}; + double r_y[] = {0.939231, 0.898373, 0.895770, 0.267192}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 u = vec2_create(u_x[i], u_y[i]); + vec2 r = vec2_normalize(u); + if (!(dbl_eq(r.x, r_x[i]) && dbl_eq(r.y, r_y[i]))) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_normalize 0"}; +} +test_result t_vec2_is_approx_equal_0() +{ + bool r[] = {true, true, false, false}; + + double t_x[] = {u_x[0], u_x[1] + 1e-4, u_x[2] + 15.0, u_x[3] + 1e-2}; + double t_y[] = {u_y[0], u_y[1] - 1e-4, u_y[2] + 15.0, u_y[3] + 1e-2}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 u = vec2_create(u_x[i], u_y[i]); + vec2 t = vec2_create(t_x[i], t_y[i]); + if (vec2_is_approx_equal(u, t, 1e-3) != r[i]) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_is_approx_equal 0"}; +} +test_result t_vec2_to_coordinates_0() +{ + uint32_t height = 300; + uint32_t width = 100; + double t_x[] = {0.25, 0.5, 0.75, 1}; + double t_y[] = {0, 1.0 / 3.0, 2.0 / 3.0, 1}; + uint32_t r_col[] = {25, 50, 74, 99}; + uint32_t r_row[] = {0, 100, 199, 299}; + + bool passed = true; + for (uint32_t i = 0; i < nb_tests; i++) + { + vec2 t = vec2_create(t_x[i], t_y[i]); + coordinates r = vec2_to_coordinates(t, width, height); + if (r.row != r_row[i] || r.column != r_col[i]) + { + passed = false; + break; + } + } + + return (test_result){.passed = passed, + .name = "Test vec2_to_coordinates 0"}; +} +//Add or remove your test function name here +const unit_test_t tests[] = { + t_vec2_create_0, + t_vec2_create_zero_0, + t_vec2_add_0, + t_vec2_sub_0, + t_vec2_mul_0, + t_vec2_dot_0, + t_vec2_norm_sqr_0, + t_vec2_norm_0, + t_vec2_normalize_0, + t_vec2_is_approx_equal_0, + t_vec2_to_coordinates_0}; + +int main() +{ + uint32_t nb_tests = sizeof(tests) / sizeof(unit_test_t); + char message[256]; + bool all_passed = true; + + for (uint32_t i = 0; i < nb_tests; i++) + { + printf("Running test n°%d: ...\n", i); + test_result r = tests[i](); + if (r.passed) + { + sprintf(message, "\t- %s : OK", r.name); + print_in_green(message); + } + else + { + all_passed = false; + sprintf(message, "\t- %s : FAILED", r.name); + print_in_red(message); + } + printf("\n"); + } + if (all_passed) + print_in_green("\nTests suite result : OK\n"); + else + print_in_red("\nTests suite result : FAILED\n"); +} \ No newline at end of file -- GitLab