Skip to content
Snippets Groups Projects
Commit 128c16ee authored by orestis.malaspin's avatar orestis.malaspin
Browse files

adding vec2 code and tests

parent d162b95c
No related branches found
No related tags found
No related merge requests found
CC=gcc
OPTS=-g -O3 -Wall -Wextra
LINK=-lm
main: main.o vec2.o
$(CC) $(OPTS) -o $@ $^ $(LINK)
main.o: main.c
$(CC) $(OPTS) -c $^
vec2.o: vec2.c vec2.h
$(CC) $(OPTS) -c $^
clean:
rm -f *.o main
\ No newline at end of file
#include <stdlib.h>
#include "vec2.h"
int main() {
vec2 v1 = vec2_create(1.0, -1.0);
// vec2_print(v1);
vec2 v2 = vec2_create(4.0, -2.0);
// vec2_print(v2);
vec2 v3 = vec2_sub(v1, v2);
vec2_print(v3);
return EXIT_SUCCESS;
}
\ No newline at end of file
CC=gcc
OPTS=-g -O3 -Wall -Wextra
LINK=-lm
vec2_tests: vec2_tests.o vec2.o
$(CC) $(OPTS) -o $@ $^ $(LINK)
test: vec2_tests
./vec2_tests
vec2_tests.o: vec2_tests.c
$(CC) $(OPTS) -c $^
vec2.o: ../vec2.c ../vec2.h
$(CC) $(OPTS) -c $^
clean:
rm -f *.o vec2_tests
\ No newline at end of file
/*
* Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MINUNIT_MINUNIT_H
#define MINUNIT_MINUNIT_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_WIN32)
#include <Windows.h>
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#define __func__ __FUNCTION__
#endif
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
/* Change POSIX C SOURCE version for pure c99 compilers */
#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
#include <unistd.h> /* POSIX flags */
#include <time.h> /* clock_gettime(), time() */
#include <sys/time.h> /* gethrtime(), gettimeofday() */
#include <sys/resource.h>
#include <sys/times.h>
#include <string.h>
#if defined(__MACH__) && defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_time.h>
#endif
#if __GNUC__ >= 5 && !defined(__STDC_VERSION__)
#define __func__ __extension__ __FUNCTION__
#endif
#else
#error "Unable to define timers for an unknown OS."
#endif
#include <stdio.h>
#include <math.h>
/* Maximum length of last message */
#define MINUNIT_MESSAGE_LEN 1024
/* Accuracy with which floats are compared */
#define MINUNIT_EPSILON 1E-12
/* Misc. counters */
static int minunit_run = 0;
static int minunit_assert = 0;
static int minunit_fail = 0;
static int minunit_status = 0;
/* Timers */
static double minunit_real_timer = 0;
static double minunit_proc_timer = 0;
/* Last message */
static char minunit_last_message[MINUNIT_MESSAGE_LEN];
/* Test setup and teardown function pointers */
static void (*minunit_setup)(void) = NULL;
static void (*minunit_teardown)(void) = NULL;
/* Definitions */
#define MU_TEST(method_name) static void method_name(void)
#define MU_TEST_SUITE(suite_name) static void suite_name(void)
#define MU__SAFE_BLOCK(block) do {\
block\
} while(0)
/* Run test suite and unset setup and teardown functions */
#define MU_RUN_SUITE(suite_name) MU__SAFE_BLOCK(\
suite_name();\
minunit_setup = NULL;\
minunit_teardown = NULL;\
)
/* Configure setup and teardown functions */
#define MU_SUITE_CONFIGURE(setup_fun, teardown_fun) MU__SAFE_BLOCK(\
minunit_setup = setup_fun;\
minunit_teardown = teardown_fun;\
)
/* Test runner */
#define MU_RUN_TEST(test) MU__SAFE_BLOCK(\
if (minunit_real_timer==0 && minunit_proc_timer==0) {\
minunit_real_timer = mu_timer_real();\
minunit_proc_timer = mu_timer_cpu();\
}\
if (minunit_setup) (*minunit_setup)();\
minunit_status = 0;\
test();\
minunit_run++;\
if (minunit_status) {\
minunit_fail++;\
printf("F");\
printf("\n%s\n", minunit_last_message);\
}\
fflush(stdout);\
if (minunit_teardown) (*minunit_teardown)();\
)
/* Report */
#define MU_REPORT() MU__SAFE_BLOCK(\
double minunit_end_real_timer;\
double minunit_end_proc_timer;\
printf("\n\n%d tests, %d assertions, %d failures\n", minunit_run, minunit_assert, minunit_fail);\
minunit_end_real_timer = mu_timer_real();\
minunit_end_proc_timer = mu_timer_cpu();\
printf("\nFinished in %.8f seconds (real) %.8f seconds (proc)\n\n",\
minunit_end_real_timer - minunit_real_timer,\
minunit_end_proc_timer - minunit_proc_timer);\
)
#define MU_EXIT_CODE minunit_fail
/* Assertions */
#define mu_check(test) MU__SAFE_BLOCK(\
minunit_assert++;\
if (!(test)) {\
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, #test);\
minunit_status = 1;\
return;\
} else {\
printf(".");\
}\
)
#define mu_fail(message) MU__SAFE_BLOCK(\
minunit_assert++;\
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\
minunit_status = 1;\
return;\
)
#define mu_assert(test, message) MU__SAFE_BLOCK(\
minunit_assert++;\
if (!(test)) {\
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\
minunit_status = 1;\
return;\
} else {\
printf(".");\
}\
)
#define mu_assert_int_eq(expected, result) MU__SAFE_BLOCK(\
int minunit_tmp_e;\
int minunit_tmp_r;\
minunit_assert++;\
minunit_tmp_e = (expected);\
minunit_tmp_r = (result);\
if (minunit_tmp_e != minunit_tmp_r) {\
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %d expected but was %d", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\
minunit_status = 1;\
return;\
} else {\
printf(".");\
}\
)
#define mu_assert_double_eq(expected, result) MU__SAFE_BLOCK(\
double minunit_tmp_e;\
double minunit_tmp_r;\
minunit_assert++;\
minunit_tmp_e = (expected);\
minunit_tmp_r = (result);\
if (fabs(minunit_tmp_e-minunit_tmp_r) > MINUNIT_EPSILON) {\
int minunit_significant_figures = 1 - log10(MINUNIT_EPSILON);\
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %.*g expected but was %.*g", __func__, __FILE__, __LINE__, minunit_significant_figures, minunit_tmp_e, minunit_significant_figures, minunit_tmp_r);\
minunit_status = 1;\
return;\
} else {\
printf(".");\
}\
)
#define mu_assert_string_eq(expected, result) MU__SAFE_BLOCK(\
const char* minunit_tmp_e = expected;\
const char* minunit_tmp_r = result;\
minunit_assert++;\
if (!minunit_tmp_e) {\
minunit_tmp_e = "<null pointer>";\
}\
if (!minunit_tmp_r) {\
minunit_tmp_r = "<null pointer>";\
}\
if(strcmp(minunit_tmp_e, minunit_tmp_r)) {\
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: '%s' expected but was '%s'", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\
minunit_status = 1;\
return;\
} else {\
printf(".");\
}\
)
/*
* The following two functions were written by David Robert Nadeau
* from http://NadeauSoftware.com/ and distributed under the
* Creative Commons Attribution 3.0 Unported License
*/
/**
* Returns the real time, in seconds, or -1.0 if an error occurred.
*
* Time is measured since an arbitrary and OS-dependent start time.
* The returned real time is only useful for computing an elapsed time
* between two calls to this function.
*/
static double mu_timer_real(void)
{
#if defined(_WIN32)
/* Windows 2000 and later. ---------------------------------- */
LARGE_INTEGER Time;
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
QueryPerformanceCounter(&Time);
Time.QuadPart *= 1000000;
Time.QuadPart /= Frequency.QuadPart;
return (double)Time.QuadPart / 1000000.0;
#elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
/* HP-UX, Solaris. ------------------------------------------ */
return (double)gethrtime( ) / 1000000000.0;
#elif defined(__MACH__) && defined(__APPLE__)
/* OSX. ----------------------------------------------------- */
static double timeConvert = 0.0;
if ( timeConvert == 0.0 )
{
mach_timebase_info_data_t timeBase;
(void)mach_timebase_info( &timeBase );
timeConvert = (double)timeBase.numer /
(double)timeBase.denom /
1000000000.0;
}
return (double)mach_absolute_time( ) * timeConvert;
#elif defined(_POSIX_VERSION)
/* POSIX. --------------------------------------------------- */
struct timeval tm;
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
{
struct timespec ts;
#if defined(CLOCK_MONOTONIC_PRECISE)
/* BSD. --------------------------------------------- */
const clockid_t id = CLOCK_MONOTONIC_PRECISE;
#elif defined(CLOCK_MONOTONIC_RAW)
/* Linux. ------------------------------------------- */
const clockid_t id = CLOCK_MONOTONIC_RAW;
#elif defined(CLOCK_HIGHRES)
/* Solaris. ----------------------------------------- */
const clockid_t id = CLOCK_HIGHRES;
#elif defined(CLOCK_MONOTONIC)
/* AIX, BSD, Linux, POSIX, Solaris. ----------------- */
const clockid_t id = CLOCK_MONOTONIC;
#elif defined(CLOCK_REALTIME)
/* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */
const clockid_t id = CLOCK_REALTIME;
#else
const clockid_t id = (clockid_t)-1; /* Unknown. */
#endif /* CLOCK_* */
if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )
return (double)ts.tv_sec +
(double)ts.tv_nsec / 1000000000.0;
/* Fall thru. */
}
#endif /* _POSIX_TIMERS */
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */
gettimeofday( &tm, NULL );
return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0;
#else
return -1.0; /* Failed. */
#endif
}
/**
* Returns the amount of CPU time used by the current process,
* in seconds, or -1.0 if an error occurred.
*/
static double mu_timer_cpu(void)
{
#if defined(_WIN32)
/* Windows -------------------------------------------------- */
FILETIME createTime;
FILETIME exitTime;
FILETIME kernelTime;
FILETIME userTime;
/* This approach has a resolution of 1/64 second. Unfortunately, Windows' API does not offer better */
if ( GetProcessTimes( GetCurrentProcess( ),
&createTime, &exitTime, &kernelTime, &userTime ) != 0 )
{
ULARGE_INTEGER userSystemTime;
memcpy(&userSystemTime, &userTime, sizeof(ULARGE_INTEGER));
return (double)userSystemTime.QuadPart / 10000000.0;
}
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
/* Prefer high-res POSIX timers, when available. */
{
clockid_t id;
struct timespec ts;
#if _POSIX_CPUTIME > 0
/* Clock ids vary by OS. Query the id, if possible. */
if ( clock_getcpuclockid( 0, &id ) == -1 )
#endif
#if defined(CLOCK_PROCESS_CPUTIME_ID)
/* Use known clock id for AIX, Linux, or Solaris. */
id = CLOCK_PROCESS_CPUTIME_ID;
#elif defined(CLOCK_VIRTUAL)
/* Use known clock id for BSD or HP-UX. */
id = CLOCK_VIRTUAL;
#else
id = (clockid_t)-1;
#endif
if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )
return (double)ts.tv_sec +
(double)ts.tv_nsec / 1000000000.0;
}
#endif
#if defined(RUSAGE_SELF)
{
struct rusage rusage;
if ( getrusage( RUSAGE_SELF, &rusage ) != -1 )
return (double)rusage.ru_utime.tv_sec +
(double)rusage.ru_utime.tv_usec / 1000000.0;
}
#endif
#if defined(_SC_CLK_TCK)
{
const double ticks = (double)sysconf( _SC_CLK_TCK );
struct tms tms;
if ( times( &tms ) != (clock_t)-1 )
return (double)tms.tms_utime / ticks;
}
#endif
#if defined(CLOCKS_PER_SEC)
{
clock_t cl = clock( );
if ( cl != (clock_t)-1 )
return (double)cl / (double)CLOCKS_PER_SEC;
}
#endif
#endif
return -1; /* Failed. */
}
#ifdef __cplusplus
}
#endif
#endif /* MINUNIT_MINUNIT_H */
#include "minunit.h"
#include "../vec2.h"
static vec2 four_two;
static vec2 minus_three_nine;
static vec2 e_x;
static vec2 e_y;
static double alpha = 0.0;
void test_setup(void) {
four_two = vec2_create(4.0, 2.0);
minus_three_nine = vec2_create(-3.0, 9.0);
e_x = vec2_create(1.0, 0.0);
e_y = vec2_create(0.0, 1.0);
alpha = 1.5;
}
void test_teardown(void) {
/* Nothing */
}
MU_TEST(test_vec2_create) {
mu_assert_double_eq(four_two.x, 4.0);
mu_assert_double_eq(four_two.y, 2.0);
mu_assert(vec2_is_approx_equal(four_two, vec2_create(4.0, 2.0), MINUNIT_EPSILON), "four_two should be (4.0, 2.0).");
mu_assert_double_eq(minus_three_nine.x, -3.0);
mu_assert_double_eq(minus_three_nine.y, 9.0);
mu_assert_double_eq(e_x.x, 1.0);
mu_assert_double_eq(e_x.y, 0.0);
mu_assert_double_eq(e_y.x, 0.0);
mu_assert_double_eq(e_y.y, 1.0);
}
MU_TEST(test_vec2_add) {
mu_assert(
vec2_is_approx_equal(
vec2_add(four_two, minus_three_nine),
vec2_create(1.0, 11.0), MINUNIT_EPSILON),
"(4,2)+(-3,9)=(1, 11)."
);
mu_assert(
vec2_is_approx_equal(
vec2_add(four_two, minus_three_nine),
vec2_add(minus_three_nine, four_two), MINUNIT_EPSILON),
"Addition is commutative."
);
}
MU_TEST(test_vec2_sub) {
mu_assert(
vec2_is_approx_equal(
vec2_sub(four_two, minus_three_nine),
vec2_create(7.0, -7.0), MINUNIT_EPSILON),
"(4,2)-(-3,9)=(7, -7)."
);
mu_assert(
vec2_is_approx_equal(
vec2_sub(four_two, minus_three_nine),
vec2_add(four_two, vec2_mul(-1.0, minus_three_nine)), MINUNIT_EPSILON),
"(4,2) - (-3,9) = (4,2) + (-1) * (-3,9)."
);
}
MU_TEST(test_vec2_mul) {
mu_assert(
vec2_is_approx_equal(
vec2_mul(alpha, minus_three_nine),
vec2_create(-4.5, 13.5), MINUNIT_EPSILON),
"1.5 * (-3,9)=(-4.5, 13.5)."
);
mu_assert(
vec2_is_approx_equal(
vec2_add(vec2_mul(4.0, e_x), vec2_mul(2.0, e_y)),
four_two, MINUNIT_EPSILON),
"4 * (1,0) + 2 * (0,1) = (4,2)."
);
}
MU_TEST(test_vec2_scalar_product) {
mu_assert_double_eq(
vec2_scalar_product(four_two, minus_three_nine),
6.0
);
mu_assert_double_eq(
vec2_scalar_product(e_x, e_y),
0.0
);
}
MU_TEST_SUITE(test_suite) {
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
MU_RUN_TEST(test_vec2_create);
MU_RUN_TEST(test_vec2_add);
MU_RUN_TEST(test_vec2_sub);
MU_RUN_TEST(test_vec2_mul);
MU_RUN_TEST(test_vec2_scalar_product);
}
int main() {
MU_RUN_SUITE(test_suite);
MU_REPORT();
return MU_EXIT_CODE;
}
#include <stdio.h>
#include <math.h>
#include "vec2.h"
vec2 vec2_create(double x_, double y_) {
vec2 v = {.x = x_, .y = y_};
return v;
}
vec2 vec2_add(vec2 lhs, vec2 rhs) {
return vec2_create(
lhs.x + rhs.x,
lhs.y + rhs.y
);
}
vec2 vec2_sub(vec2 lhs, vec2 rhs) {
return vec2_create(
lhs.x - rhs.x,
lhs.y - rhs.y
);
}
vec2 vec2_mul(double scalar, vec2 lhs) {
return vec2_create(
scalar * lhs.x,
scalar * lhs.y
);
}
double vec2_scalar_product(vec2 lhs, vec2 rhs) {
return lhs.x * rhs.x + lhs.y * rhs.y;
}
double vec2_norm_sqr(vec2 v) {
return vec2_scalar_product(v, v);
}
double vec2_norm(vec2 v) {
return sqrt(vec2_norm_sqr(v));
}
bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps) {
return vec2_norm(vec2_sub(lhs, rhs)) < eps;
}
void vec2_print(vec2 v) {
printf("x = %f, y = %f\n", v.x, v.y);
}
\ No newline at end of file
#ifndef _VEC2_H_
#define _VEC2_H_
#include <stdbool.h>
typedef struct _vec2 {
double x, y;
} vec2;
vec2 vec2_create(double x_, double y_);
vec2 vec2_add(vec2 lhs, vec2 rhs);
vec2 vec2_sub(vec2 lhs, vec2 rhs);
vec2 vec2_mul(double scalar, vec2 lhs);
double vec2_scalar_product(vec2 lhs, vec2 rhs);
double vec2_norm_sqr(vec2 v);
double vec2_norm(vec2 v);
bool vec2_is_approx_equal(vec2 lhs, vec2 rhs, double eps);
void vec2_print(vec2 v);
#endif
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment