diff --git a/c/complex-numbers/GNUmakefile b/c/complex-numbers/GNUmakefile new file mode 100644 index 0000000..ec085d0 --- /dev/null +++ b/c/complex-numbers/GNUmakefile @@ -0,0 +1,51 @@ +# The original 'makefile' has a flaw: +# 1) it overrides CFLAGS +# 2) it does not pass extra "FLAGS" to $(CC) that could come from environment +# +# It means : +# - we need to edit 'makefile' for different builds (DEBUG, etc...), which is +# not practical at all. +# - Also, it does not allow to run all tests without editing the test source +# code. +# +# To use this makefile (GNU make only): +# "make": build with all predefined tests (without editing test source code) +# "make debugall": build with all predefined tests and debug code +# "make mem": perform memcheck with all tests enabled +# "make unit": build standalone (unit) test +# "make debug": build standalone test with debugging code +# +# Original 'makefile' targets can be used (test, memcheck, clean, ...) + +.PHONY: default all mem unit debug std debugtest + +default: all + +# default is to build with all predefined tests +BUILD := teststall + +include makefile + +all: CFLAGS+=-DTESTALL +all: clean test + +debugall: CFLAGS+=-DDEBUG +debugall: all + +debugtest: CFLAGS+=-DDEBUG +debugtest: test + +mem: CFLAGS+=-DTESTALL +mem: clean memcheck + +unit: CFLAGS+=-DUNIT_TEST +unit: clean std + +debug: CFLAGS+=-DUNIT_TEST -DDEBUG +debug: clean std + +debugtest: CFLAGS+=-DDEBUG +debugtest: test + +std: src/*.c src/*.h + $(CC) $(CFLAGS) src/*.c -o test.out diff --git a/c/complex-numbers/README.md b/c/complex-numbers/README.md new file mode 100644 index 0000000..3055202 --- /dev/null +++ b/c/complex-numbers/README.md @@ -0,0 +1,67 @@ +# Complex Numbers + +A complex number is a number in the form `a + b * i` where `a` and `b` are real and `i` satisfies `i^2 = -1`. + +`a` is called the real part and `b` is called the imaginary part of `z`. +The conjugate of the number `a + b * i` is the number `a - b * i`. +The absolute value of a complex number `z = a + b * i` is a real number `|z| = sqrt(a^2 + b^2)`. The square of the absolute value `|z|^2` is the result of multiplication of `z` by its complex conjugate. + +The sum/difference of two complex numbers involves adding/subtracting their real and imaginary parts separately: +`(a + i * b) + (c + i * d) = (a + c) + (b + d) * i`, +`(a + i * b) - (c + i * d) = (a - c) + (b - d) * i`. + +Multiplication result is by definition +`(a + i * b) * (c + i * d) = (a * c - b * d) + (b * c + a * d) * i`. + +The reciprocal of a non-zero complex number is +`1 / (a + i * b) = a/(a^2 + b^2) - b/(a^2 + b^2) * i`. + +Dividing a complex number `a + i * b` by another `c + i * d` gives: +`(a + i * b) / (c + i * d) = (a * c + b * d)/(c^2 + d^2) + (b * c - a * d)/(c^2 + d^2) * i`. + +Raising e to a complex exponent can be expressed as `e^(a + i * b) = e^a * e^(i * b)`, the last term of which is given by Euler's formula `e^(i * b) = cos(b) + i * sin(b)`. + +Implement the following operations: + - addition, subtraction, multiplication and division of two complex numbers, + - conjugate, absolute value, exponent of a given complex number. + + +Assume the programming language you are using does not have an implementation of complex numbers. + +## Getting Started + +Make sure you have read the "Guides" section of the +[C track][c-track] on the Exercism site. This covers +the basic information on setting up the development environment expected +by the exercises. + +## Passing the Tests + +Get the first test compiling, linking and passing by following the [three +rules of test-driven development][3-tdd-rules]. + +The included makefile can be used to create and run the tests using the `test` +task. + + make test + +Create just the functions you need to satisfy any compiler errors and get the +test to fail. Then write just enough code to get the test to pass. Once you've +done that, move onto the next test. + +As you progress through the tests, take the time to refactor your +implementation for readability and expressiveness and then go on to the next +test. + +Try to use standard C99 facilities in preference to writing your own +low-level algorithms or facilities by hand. + +## Source + +Wikipedia [https://en.wikipedia.org/wiki/Complex_number](https://en.wikipedia.org/wiki/Complex_number) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + +[c-track]: https://exercism.io/my/tracks/c +[3-tdd-rules]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd diff --git a/c/complex-numbers/makefile b/c/complex-numbers/makefile new file mode 100644 index 0000000..d005aac --- /dev/null +++ b/c/complex-numbers/makefile @@ -0,0 +1,38 @@ +### If you wish to use extra libraries (math.h for instance), +### add their flags here (-lm in our case) in the "LIBS" variable. + +LIBS = -lm + +### +CFLAGS = -std=c99 +CFLAGS += -g +CFLAGS += -Wall +CFLAGS += -Wextra +CFLAGS += -pedantic +CFLAGS += -Werror +CFLAGS += -Wmissing-declarations +CFLAGS += -DUNITY_SUPPORT_64 +CFLAGS += -DUNITY_INCLUDE_DOUBLE + +ASANFLAGS = -fsanitize=address +ASANFLAGS += -fno-common +ASANFLAGS += -fno-omit-frame-pointer + +.PHONY: test +test: tests.out + @./tests.out + +.PHONY: memcheck +memcheck: test/*.c src/*.c src/*.h + @echo Compiling $@ + @$(CC) $(ASANFLAGS) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o memcheck.out $(LIBS) + @./memcheck.out + @echo "Memory check passed" + +.PHONY: clean +clean: + rm -rf *.o *.out *.out.dSYM + +tests.out: test/*.c src/*.c src/*.h + @echo Compiling $@ + @$(CC) $(CFLAGS) src/*.c test/vendor/unity.c test/*.c -o tests.out $(LIBS) diff --git a/c/complex-numbers/src/complex_numbers.c b/c/complex-numbers/src/complex_numbers.c new file mode 100644 index 0000000..a9bbf4f --- /dev/null +++ b/c/complex-numbers/src/complex_numbers.c @@ -0,0 +1,96 @@ +#include "complex_numbers.h" + +#ifdef USE_COMPLEX_FUNCTIONS + +complex_t c_add(complex_t a, complex_t b) +{ + return (complex_t) { + .real = a.real+b.real, + .imag = a.imag+b.imag + }; +} + +complex_t c_sub(complex_t a, complex_t b) +{ + return (complex_t) { + .real = a.real-b.real, + .imag = a.imag-b.imag + }; +} + +complex_t c_mul(complex_t a, complex_t b) +{ + return (complex_t) { + .real = a.real*b.real - a.imag*b.imag, + .imag = a.imag*b.real + a.real*b.imag, + }; +} + +complex_t c_div(complex_t a, complex_t b) +{ + double d = b.real*b.real + b.imag*b.imag; + return (complex_t) { + .real = (a.real*b.real + a.imag*b.imag)/d, + .imag = (a.imag*b.real - a.real*b.imag)/d + }; +} + +double c_abs(complex_t x) +{ + return sqrt(x.real*x.real + x.imag*x.imag); +} + +complex_t c_conjugate(complex_t x) +{ + return (complex_t) { + .real = x.real, + .imag = -x.imag + }; +} + +double c_real(complex_t x) +{ + return x.real; +} + +double c_imag(complex_t x) +{ + return x.imag; +} + +complex_t c_exp(complex_t x) +{ + return (complex_t) { + .real = exp(x.real)*cos(x.imag), + .imag = exp(x.real)*sin(x.imag) + }; +} + +#endif + +/* See GNUmakefile below for explanation + * https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile + */ +#ifdef UNIT_TEST +#include +#include + +int main(int ac, char **av) +{ + int arg=1; + complex_t c1, c2, c3; + + for (; arg + +typedef struct { + double real; + double imag; +} complex_t; + +/* default is to use macros */ +#ifdef USE_COMPLEX_FUNCTIONS + +complex_t c_add(complex_t a, complex_t b); +complex_t c_sub(complex_t a, complex_t b); +complex_t c_mul(complex_t a, complex_t b); +complex_t c_div(complex_t a, complex_t b); +double c_abs(complex_t x); +complex_t c_conjugate(complex_t x); +double c_real(complex_t x); +double c_imag(complex_t x); +complex_t c_exp(complex_t x); + +#else + +#define c_add(a,b) (complex_t) { \ + (a).real+(b).real, \ + (a).imag+(b).imag } + +#define c_sub(a,b) (complex_t) { \ + (a).real-(b).real, \ + (a).imag-(b).imag } + +#define c_mul(a,b) (complex_t) { \ + (a).real*(b).real - (a).imag*(b).imag, \ + (a).imag*(b).real + (a).real*(b).imag } + +#define c_div(a,b) (complex_t) { \ + ((a).real*(b).real + (a).imag*(b).imag)/ \ + ((b).real*(b).real + (b).imag*(b).imag), \ + ((a).imag*(b).real - (a).real*(b).imag)/ \ + ((b).real*(b).real + (b).imag*(b).imag) } + +#define c_exp(x) (complex_t) { \ + exp((x).real) * cos((x).imag), \ + exp((x).real) * sin((x).imag) } + +#define c_abs(x) { sqrt((x).real*(x).real + (x).imag*(x).imag) } + +#define c_conjugate(x) (complex_t){ (x).real, -(x).imag } + +#define c_real(x) (x).real + +#define c_imag(x) (x).imag + + +#endif + +/* See GNUmakefile below for explanation + * https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile + */ +#if defined UNIT_TEST || defined DEBUG +#include +#include +#endif +#ifdef TESTALL +#undef TEST_IGNORE +#define TEST_IGNORE() {} +#endif + +#endif diff --git a/c/grade-school/src/grade_school.c b/c/grade-school/src/grade_school.c index 1ee6b91..1044f04 100644 --- a/c/grade-school/src/grade_school.c +++ b/c/grade-school/src/grade_school.c @@ -39,7 +39,7 @@ int add_student(char *s, uint8_t g) */ roster_t get_grade(uint8_t g) { - static roster_t r; + roster_t r; unsigned i, j=0; for (i=0; i= NBITS || i <= max) { - sq2 = (1L << (j >> 1)); + sq2 = (1 << (j >> 1)); break; } } @@ -45,11 +44,18 @@ unsigned square_root(unsigned i) #ifdef UNIT_TEST int main(int ac, char **av) { - unsigned i, j; + unsigned i; +/* int arg=1; + for (; arg +#include + +/* V1: initial version + * V2: bug fix: force full unsigned allocation instead of bytes. + */ +#include "sum_of_multiples.h" + +#define BITS (sizeof(unsigned)*8) + +#define getbit(i) (!!(sieve[(i) / BITS] & (1 << ((i) % BITS)))) +#define setbit(i) (sieve[(i) / BITS] |= (1 << ((i) % BITS))) + +/* use a kind of eratosthenes's sieve, to avoid the trivial solution :-) + */ +unsigned sum(const unsigned *f, const size_t n, const unsigned l) +{ + unsigned sieve_size = (l-1)/BITS+1; + unsigned num, i, res=0; + unsigned *sieve; + + sieve = calloc(sieve_size, sizeof(unsigned)); /* l bits array */ + if (!sieve) + return 0; + for (i=0; i2) { + last=atol(av[1]); + for (i=2; i + +unsigned int sum(const unsigned int *factors, + const size_t number_of_factors, const unsigned int limit); + +/* See GNUmakefile below for explanation + * https://github.com/braoult/exercism/blob/master/c/templates/GNUmakefile + */ +#if defined UNIT_TEST || defined DEBUG +#include +#include +#endif +#ifdef TESTALL +#undef TEST_IGNORE +#define TEST_IGNORE() {} +#endif + +#endif