Browse Source

No need to link math library now; Added abs, pow, sqrt alternatives for projects with no stdlib

master
parent
commit
cc4452540d
  1. 4
      Makefile
  2. 180
      src/math/misc.c
  3. 47
      src/math/misc.h
  4. 8
      src/math/vector.c
  5. 2
      src/math/vector.h
  6. 41
      testing/test.c

4
Makefile

@ -17,13 +17,13 @@ lib:
ar rcs $(BINDIR)/$(LIBNAME) $(BUILDDIR)/*.o ar rcs $(BINDIR)/$(LIBNAME) $(BUILDDIR)/*.o
test: test:
$(CC) $(DEFAULTCCFLAGS) $(TESTDIR)/$(TESTBIN).c $(SRCDIR)/*/*.c -o $(TESTDIR)/$(TESTBIN) -lm && \ $(CC) $(DEFAULTCCFLAGS) $(TESTDIR)/$(TESTBIN).c $(SRCDIR)/*/*.c -o $(TESTDIR)/$(TESTBIN) && \
cd $(TESTDIR) && \ cd $(TESTDIR) && \
./$(TESTBIN) && \ ./$(TESTBIN) && \
rm $(TESTBIN) rm $(TESTBIN)
test_static: lib test_static: lib
$(CC) $(DEFAULTCCFLAGS) $(TESTDIR)/$(TESTBIN).c $(BINDIR)/$(LIBNAME) -static -lm -o $(TESTDIR)/$(TESTBIN) && \ $(CC) $(DEFAULTCCFLAGS) $(TESTDIR)/$(TESTBIN).c $(BINDIR)/$(LIBNAME) -static -o $(TESTDIR)/$(TESTBIN) && \
cd $(TESTDIR) && \ cd $(TESTDIR) && \
./$(TESTBIN) && \ ./$(TESTBIN) && \
rm $(TESTBIN) rm $(TESTBIN)

180
src/math/misc.c

@ -0,0 +1,180 @@
/*
The MIT License (MIT)
Copyright © 2023 Kasyanov Nikolay Alexeyevich (Unbewohnte)
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.
*/
// Returns an absolute value of n
#include "misc.h"
char absch(char n) {
if (n >= 0) {
return n;
} else {
return -n;
}
}
// Returns an absolute value of n
short abssh(short n) {
if (n >= 0) {
return n;
} else {
return -n;
}
}
// Returns an absolute value of n
int absi(int n) {
if (n >= 0) {
return n;
} else {
return -n;
}
}
// Returns an absolute value of n
long absl(long n) {
if (n >= 0) {
return n;
} else {
return -n;
}
}
// Returns an absolute value of n
long long absll(long long n) {
if (n >= 0) {
return n;
} else {
return -n;
}
}
// Returns an absolute value of n
float absf(float n) {
if (n >= 0.0f) {
return n;
} else {
return -n;
}
}
// Returns an absolute value of n
double absd(double n) {
if (n >= 0.0f) {
return n;
} else {
return -n;
}
}
// Returns an absolute value of n
long double absld(long double n) {
if (n >= 0.0f) {
return n;
} else {
return -n;
}
}
long double n_root(long double a, unsigned int n, unsigned int max_iter, long double epsilon) {
if (n == 1 || a == 0) {
return a;
}
float prev_val = 1;
float val = 0;
for (unsigned int i = 0; i < max_iter; i++) {
val = (1.0 / n) * ((n - 1) * prev_val + a / powerl(prev_val, n-1));
if (absld(prev_val - val) < epsilon) {
return val;
}
prev_val = val;
}
return val;
}
// Returns the approximate result of base^exp
float powerf(float base, float exp) {
// all zeroes|base is zero, but exp is not
if ((base == 0.0f && exp == 0.0f) || (base == 0.0f && exp != 0.0f)) {
return 0.0f;
}
// exp is 0
if (exp == 0.0f) {
return 1.0f;
}
// exp is negative
if (exp < 0.0f) {
return 1.0 / powerf(base, -exp);
}
// exp is in (0.0; 1.0)
if (exp > 0.0f && exp < 1.0f) {
return (float) n_root(base, 1.0 / exp, 500, 0.00001f);
}
// exp is even
if ((int) exp % 2 == 0) {
float hpow = powerf(base, exp / 2.0f);
return hpow * hpow;
}
// exp is integer
return base * powerf(base, exp-1.0);
}
// Returns the approximate result of base^exp
long double powerl(long double base, long double exp) {
// all zeroes|base is zero, but exp is not
if ((base == 0.0f && exp == 0.0f) || (base == 0.0f && exp != 0.0f)) {
return 0.0f;
}
// exp is 0
if (exp == 0.0f) {
return 1.0f;
}
// exp is negative
if (exp < 0.0f) {
return 1.0 / powerl(base, -exp);
}
// exp is in (0.0; 1.0)
if (exp > 0.0f && exp < 1.0f) {
return n_root(base, 1.0 / exp, 500, 0.0000000001f);
}
// exp is even
if ((int) exp % 2 == 0) {
float hpow = powerl(base, exp / 2.0f);
return hpow * hpow;
}
// exp is integer
return base * powerl(base, exp-1.0);
}
// Returns the approximate result of square root of n
float sqrootf(float n) {
return powerf(n, 0.5f);
}
// Returns the approximate result of square root of n
float sqrootl(long double n) {
return powerl(n, 0.5);
}

47
src/math/misc.h

@ -0,0 +1,47 @@
/*
The MIT License (MIT)
Copyright © 2023 Kasyanov Nikolay Alexeyevich (Unbewohnte)
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.
*/
// Returns an absolute value of n
char absch(char n);
// Returns an absolute value of n
short abssh(short n);
// Returns an absolute value of n
int absi(int n);
// Returns an absolute value of n
long absl(long n);
// Returns an absolute value of n
long long absll(long long n);
// Returns an absolute value of n
float absf(float n);
// Returns an absolute value of n
double absd(double n);
// Returns an absolute value of n
long double absld(long double n);
// Returns the approximate result of base^exp
float powerf(float base, float exp);
// Returns the approximate result of base^exp
long double powerl(long double base, long double exp);
// Returns the approximate result of square root of n
float sqrootf(float n);
// Returns the approximate result of square root of n
float sqrootl(long double n);

8
src/math/vector.c

@ -14,12 +14,12 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
// Calculate vector's length // Calculate vector's length
long double vec2_len(vec2 vec) { long double vec2_len(vec2 vec) {
return sqrtl((long double) (vec.x*vec.x) + (long double) (vec.y*vec.y)); return sqrootl((long double) (vec.x*vec.x) + (long double) (vec.y*vec.y));
} }
// Calculate vector's length // Calculate vector's length
long double vec2f_len(vec2f vec) { long double vec2f_len(vec2f vec) {
return sqrtl(vec.x*vec.x + vec.y*vec.y); return sqrootl(vec.x*vec.x + vec.y*vec.y);
} }
// Add 2 vectors together // Add 2 vectors together
@ -54,7 +54,7 @@ long double vec2f_angle(vec2f a, vec2f b) {
// Calculate vector's length // Calculate vector's length
long double vec3_len(vec3 vec) { long double vec3_len(vec3 vec) {
return sqrt( return sqrootl(
(long double) (vec.x*vec.x) + (long double) (vec.x*vec.x) +
(long double) (vec.y*vec.y) + (long double) (vec.y*vec.y) +
(long double) (vec.z*vec.z) (long double) (vec.z*vec.z)
@ -63,7 +63,7 @@ long double vec3_len(vec3 vec) {
// Calculate vector's length // Calculate vector's length
long double vec3f_len(vec3f vec) { long double vec3f_len(vec3f vec) {
return sqrtl( return sqrootl(
vec.x*vec.x + vec.x*vec.x +
vec.y*vec.y + vec.y*vec.y +
vec.z*vec.z vec.z*vec.z

2
src/math/vector.h

@ -10,7 +10,7 @@ The above copyright notice and this permission notice shall be included in all c
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. 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.
*/ */
#include <math.h> #include "misc.h"
typedef struct vec2 { typedef struct vec2 {
long long int x; long long int x;

41
testing/test.c

@ -1,7 +1,7 @@
/* /*
The MIT License (MIT) The MIT License (MIT)
Copyright © 2022 Kasyanov Nikolay Alexeyevich (Unbewohnte) Copyright © 2022, 2023 Kasyanov Nikolay Alexeyevich (Unbewohnte)
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: 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:
@ -24,6 +24,7 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
#include "../src/fs/fs.h" #include "../src/fs/fs.h"
#include "../src/bits/bits.h" #include "../src/bits/bits.h"
#include "../src/math/vector.h" #include "../src/math/vector.h"
#include "../src/math/misc.h"
#include "../src/datastruct/cvec.h" #include "../src/datastruct/cvec.h"
int test_rng() { int test_rng() {
@ -176,7 +177,7 @@ int test_vector() {
vec2 vec2d_other = {3, 2}; vec2 vec2d_other = {3, 2};
long long int multiplied; long long int multiplied;
if (fabsl(vec2_len(vec2d) - 3.606f) > threshold) { if (absld(vec2_len(vec2d) - 3.606f) > threshold) {
printf("[ERROR] Vector length calculation is wrong: expeted to be %f (+-%Lf); got %Lf\n", printf("[ERROR] Vector length calculation is wrong: expeted to be %f (+-%Lf); got %Lf\n",
3.606f, threshold, vec2_len(vec2d) 3.606f, threshold, vec2_len(vec2d)
); );
@ -191,7 +192,7 @@ int test_vector() {
vec2d = (vec2){3, 4}; vec2d = (vec2){3, 4};
vec2d_other = (vec2){4, 3}; vec2d_other = (vec2){4, 3};
if (fabsl(vec2_angle(vec2d, vec2d_other) - 0.96f) > threshold) { if (absld(vec2_angle(vec2d, vec2d_other) - 0.96f) > threshold) {
printf("[ERROR] Failed to calculate angle between 2 vectors: expected to be %f (+-%Lf); got %Lf\n", printf("[ERROR] Failed to calculate angle between 2 vectors: expected to be %f (+-%Lf); got %Lf\n",
0.96f, threshold, vec2_angle(vec2d, vec2d_other) 0.96f, threshold, vec2_angle(vec2d, vec2d_other)
); );
@ -211,12 +212,46 @@ int test_vector() {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
int test_misc() {
const float num1 = -0.5;
if (absf(num1) != 0.5f) {
printf("[ERROR] Failed to get absolute value of %f: got %f; expected %f", num1, absf(num1), -num1);
return EXIT_FAILURE;
}
const float abs_num1_pow2 = absf(num1) * absf(num1);
if (powerf(absf(num1), 2.0f) != abs_num1_pow2) {
printf("[ERROR] Failed to get %f to the power of 2: got %f; expected %f", absf(num1), powerf(absf(num1), 2.0f), abs_num1_pow2);
return EXIT_FAILURE;
}
const int num2 = 2;
const float result = powerf(powerf(powerf((float) num2, 2.0f), 2.0f), 2.0f);
if (result != 256.0f) {
printf("[ERROR] Failed to get ((%d^2)^2)^2: got %f; expected %d", num2, result, 256);
return EXIT_FAILURE;
}
const int num3 = 4;
if (sqrootf(num3) != 2.0) {
printf("[ERROR] Failed to calculate square root of %d: got %f; expected %d", num3, sqrootf(num3), 2);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int test_math() { int test_math() {
if (test_vector() == EXIT_FAILURE) { if (test_vector() == EXIT_FAILURE) {
printf("[ERROR] Vector test failed\n"); printf("[ERROR] Vector test failed\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (test_misc() == EXIT_FAILURE) {
printf("[ERROR] Misc test failed\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

Loading…
Cancel
Save