diff options
author | Tyler Murphy <=> | 2023-07-16 02:54:32 -0400 |
---|---|---|
committer | Tyler Murphy <=> | 2023-07-16 02:54:32 -0400 |
commit | fbf131b5c043b27e0b1543374bb144e3e426f723 (patch) | |
tree | 07f0ab2fc107b36621d5ae95480e6a91e332548b /libk | |
download | finix-fbf131b5c043b27e0b1543374bb144e3e426f723.tar.gz finix-fbf131b5c043b27e0b1543374bb144e3e426f723.tar.bz2 finix-fbf131b5c043b27e0b1543374bb144e3e426f723.zip |
initial
Diffstat (limited to 'libk')
-rw-r--r-- | libk/Makefile | 20 | ||||
-rw-r--r-- | libk/compile_flags.txt | 10 | ||||
-rw-r--r-- | libk/include/ctype.h | 4 | ||||
-rw-r--r-- | libk/include/math.h | 62 | ||||
-rw-r--r-- | libk/include/stdlib.h | 25 | ||||
-rw-r--r-- | libk/include/string.h | 13 | ||||
-rw-r--r-- | libk/include/sys.h | 51 | ||||
-rw-r--r-- | libk/src/ctype.c | 19 | ||||
-rw-r--r-- | libk/src/internal/libm.h | 32 | ||||
-rw-r--r-- | libk/src/math/abs.c | 14 | ||||
-rw-r--r-- | libk/src/math/ceil.c | 59 | ||||
-rw-r--r-- | libk/src/math/copysign.c | 20 | ||||
-rw-r--r-- | libk/src/math/fact.c | 29 | ||||
-rw-r--r-- | libk/src/math/fclamp.c | 13 | ||||
-rw-r--r-- | libk/src/math/floor.c | 55 | ||||
-rw-r--r-- | libk/src/math/fma.c | 38 | ||||
-rw-r--r-- | libk/src/math/fmod.c | 129 | ||||
-rw-r--r-- | libk/src/math/frexp.c | 19 | ||||
-rw-r--r-- | libk/src/math/pow.c | 152 | ||||
-rw-r--r-- | libk/src/math/sqrt.c | 36 | ||||
-rw-r--r-- | libk/src/math/trig.c | 62 | ||||
-rw-r--r-- | libk/src/stdlib.c | 164 | ||||
-rw-r--r-- | libk/src/string.c | 61 |
23 files changed, 1087 insertions, 0 deletions
diff --git a/libk/Makefile b/libk/Makefile new file mode 100644 index 0000000..97bc3cd --- /dev/null +++ b/libk/Makefile @@ -0,0 +1,20 @@ +include ../.env + +SRC = $(shell find src -type f -name "*.c") +OBJ = $(patsubst %.c,bin/%.o, $(SRC)) +CFLAGS += -Iinclude -Isrc -std=c99 + +.PHONY: all + +all: bin/libk.a + +$(OBJ): bin/%.o : %.c + @mkdir -p $(@D) + $(CC) -c $(CFLAGS) -o $@ $< + +bin/libk.a: $(OBJ) + @mkdir -p $(@D) + $(AR) rcs $@ $(OBJ) + +clean: + rm -fr bin diff --git a/libk/compile_flags.txt b/libk/compile_flags.txt new file mode 100644 index 0000000..2048fc0 --- /dev/null +++ b/libk/compile_flags.txt @@ -0,0 +1,10 @@ +-c +-std=c99 +-Wall +-Wextra +-pedantic +-O2 +-ffreestanding +-Isrc +-Iinclude +-nostdlib diff --git a/libk/include/ctype.h b/libk/include/ctype.h new file mode 100644 index 0000000..289297e --- /dev/null +++ b/libk/include/ctype.h @@ -0,0 +1,4 @@ +#pragma once + +int isspace(int c); +int isdigit(int c); diff --git a/libk/include/math.h b/libk/include/math.h new file mode 100644 index 0000000..9682103 --- /dev/null +++ b/libk/include/math.h @@ -0,0 +1,62 @@ +#pragma once + +#define PI 3.14159265358979323846 +#define E 0.57721566490153286060 + +#define NAN 0x7ff8000000000000 +#define INFINITY 0x7ff0000000000000 +#define NEG_INFINITY 0xfff0000000000000 + +double frexp(double arg, int* exp); +float frexpf(float arg, int* exp); + +double sqrt(double num); +float sqrtf(float num); + +double pow(double num, double raise); +float powf(float num, float raise); + +#define exp(x) pow(E, x) +#define expf(x) powf(E, x) + +double fabs(double num); +float fabsf(float num); + +double floor(double x); +float floorf(float x); + +double ceil(double x); +float ceilf(float x); + +double fma(double x, double y, double z); +float fmaf(float x, float y, float z); + +double copysign(double n, double s); +float copysignf(float n, float s); + +double fmod(double x, double y); +float fmodf(float x, float y); + +double fclamp(double x, double l, double h); +float fclampf(float x, float l, float h); + +#define isnan(n) (n == NAN) +#define isinf(n) (n == INFINITY) + +double sin(double r); +double cos(double r); +double tan(double r); + +double csc(double r); +double sec(double r); +double cot(double r); + +double sinh(double r); +double cosh(double r); +double tanh(double r); + +double csch(double r); +double sech(double r); +double coth(double r); + +unsigned long long fact(unsigned int num); diff --git a/libk/include/stdlib.h b/libk/include/stdlib.h new file mode 100644 index 0000000..1cb07a0 --- /dev/null +++ b/libk/include/stdlib.h @@ -0,0 +1,25 @@ +#pragma once + +#include <stddef.h> + +char itoc(int i); +int ctoi(char c); + +int atoi(const char* s); +long int atol(const char* s); +long long int atoll(const char* s); + +char *itoa(int n, char *buffer, int radix); +char *ltoa(long int n, char *buffer, int radix); +char *utoa(unsigned int n, char *buffer, int radix); +char *ultoa(unsigned long int n, char *buffer, int radix); +char *ftoa(float f, char *buffer); + +int strtoi(const char *str, char **endptr, int base); +long int strtol(const char *str, char **endptr, int base); +long long int strtoll(const char *str, char **endptr, int base); + +extern void *malloc(size_t size); +extern void *realloc(void *ptr, size_t size); +extern void *calloc(size_t count, size_t size); +extern void free(void *ptr); diff --git a/libk/include/string.h b/libk/include/string.h new file mode 100644 index 0000000..880bc8b --- /dev/null +++ b/libk/include/string.h @@ -0,0 +1,13 @@ +#pragma once + +#include <stddef.h> + +int memcmp(const void *vl, const void *vr, size_t n); +void *memcpy(void *restrict dest, const void *restrict src, size_t n); +void *memmove(void *dest, const void *src, size_t n); +void *memset(void *dest, int c, size_t n); +char *strcpy(char *restrict dest, const char *restrict src); +char *strncpy(char *restrict dest, const char *restrict src, size_t n); +size_t strlen(const char *s); +int strncmp( const char* lhs, const char* rhs, size_t count ); + diff --git a/libk/include/sys.h b/libk/include/sys.h new file mode 100644 index 0000000..75618e8 --- /dev/null +++ b/libk/include/sys.h @@ -0,0 +1,51 @@ +#include <stdint.h> + +static inline uint8_t inb(uint16_t port) { + uint8_t ret; + __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void outb(uint16_t port, uint8_t val) { + __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); +} + +static inline uint16_t inw(uint16_t port) { + uint16_t ret; + __asm__ volatile ("inw %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void outw(uint16_t port, uint16_t val) { + __asm__ volatile ("outw %0, %1" : : "a"(val), "Nd"(port)); +} + +static inline uint32_t inl(uint16_t port) { + uint32_t ret; + __asm__ volatile ("inl %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; +} + +static inline void outl(uint16_t port, uint32_t val) { + __asm__ volatile ("outl %0, %1" : : "a"(val), "Nd"(port)); +} + +static inline void io_wait(void) { + outb(0x80, 0); +} + +static inline void int_enable(void) { + __asm__ volatile ("sti"); +} + +static inline void int_disable(void) { + __asm__ volatile ("cli"); +} + +static inline void int_wait(void) { + __asm__ volatile ("sti; hlt"); +} + +static inline void halt(void) { + __asm__ volatile ("cli; hlt"); +} diff --git a/libk/src/ctype.c b/libk/src/ctype.c new file mode 100644 index 0000000..2e8714f --- /dev/null +++ b/libk/src/ctype.c @@ -0,0 +1,19 @@ +#include <ctype.h> + +int isspace(int c) { + switch (c) { + case ' ': + case '\t': + case '\v': + case '\f': + case '\r': + case '\n': + return 1; + default: + return 0; + } +} + +int isdigit(int c) { + return c - '0' > -1 && c - '0' < 10; +} diff --git a/libk/src/internal/libm.h b/libk/src/internal/libm.h new file mode 100644 index 0000000..6c47502 --- /dev/null +++ b/libk/src/internal/libm.h @@ -0,0 +1,32 @@ +#pragma once + +#define fp_force_evalf fp_force_evalf +static inline void fp_force_evalf(float x) { + volatile float y; + y = x; + (void)y; +} + +#define fp_force_eval fp_force_eval +static inline void fp_force_eval(double x) { + volatile double y; + y = x; + (void)y; +} + +#define fp_force_evall fp_force_evall +static inline void fp_force_evall(long double x) { + volatile long double y; + y = x; + (void)y; +} + +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else if (sizeof(x) == sizeof(double)) { \ + fp_force_eval(x); \ + } else { \ + fp_force_evall(x); \ + } \ +} while(0) diff --git a/libk/src/math/abs.c b/libk/src/math/abs.c new file mode 100644 index 0000000..1757272 --- /dev/null +++ b/libk/src/math/abs.c @@ -0,0 +1,14 @@ +#include <math.h> +#include <stdint.h> + +float fabsf(float num) { + union {float f; uint32_t i;} u = {num}; + u.i &= 0x7fffffff; + return u.f; +} + +double fabs(double num) { + union {double f; uint64_t i;} u = {num}; + u.i &= -1ULL/2; + return u.f; +} diff --git a/libk/src/math/ceil.c b/libk/src/math/ceil.c new file mode 100644 index 0000000..17b667f --- /dev/null +++ b/libk/src/math/ceil.c @@ -0,0 +1,59 @@ +#include <stdint.h> +#include <float.h> +#include <math.h> + +#include "internal/libm.h" + +#define EPS DBL_EPSILON + +static const double toint = 1/EPS; + +double ceil(double x) +{ + union {double f; uint64_t i;} u = {x}; + int e = u.i >> 52 & 0x7ff; + double y; + + if (e >= 0x3ff+52 || x == 0) + return x; + + if (u.i >> 63) { + y = x - toint + toint - x; + } else { + y = x + toint - toint - x; + } + + if (e <= 0x3ff-1) { + FORCE_EVAL(y); + return u.i >> 63 ? -0.0 : 1; + } + + if (y < 0) + return x + y + 1; + return x + y; +} + +float ceilf(float x) { + union {float f; uint32_t i;} u = {x}; + int e = (int)(u.i >> 23 & 0xff) - 0x7f; + uint32_t m; + + if (e >= 23) + return x; + if (e >= 0) { + m = 0x007fffff >> e; + if ((u.i & m) == 0) + return x; + FORCE_EVAL(x + 0x1p120f); + if (u.i >> 31 == 0) + u.i += m; + u.i &= ~m; + } else { + FORCE_EVAL(x + 0x1p120f); + if (u.i >> 31) + u.f = -0.0; + else if (u.i << 1) + u.f = 1.0; + } + return u.f; +} diff --git a/libk/src/math/copysign.c b/libk/src/math/copysign.c new file mode 100644 index 0000000..fd5fd4f --- /dev/null +++ b/libk/src/math/copysign.c @@ -0,0 +1,20 @@ +#include <math.h> +#include <stdint.h> + +#define DMASK 0x8000000000000000 + +double copysign(double n, double s) { + union {double f; uint64_t i;} sb = {s}; + union {double f; uint64_t i;} nb = {n}; + nb.i = (nb.i & ~DMASK) | (sb.i & DMASK); + return nb.f; +} + +#define FMASK 0x80000000 + +float copysignf(float n, float s) { + union {float f; uint32_t i;} sb = {s}; + union {float f; uint32_t i;} nb = {n}; + nb.i = (nb.i & ~FMASK) | (sb.i & FMASK); + return nb.f; +} diff --git a/libk/src/math/fact.c b/libk/src/math/fact.c new file mode 100644 index 0000000..a146e4d --- /dev/null +++ b/libk/src/math/fact.c @@ -0,0 +1,29 @@ +#include <math.h> + +static unsigned int FACT_TABLE[] = { + 1, // 0 + 1, // 1 + 2, // 2 + 6, // 3 + 24, // 4 + 120, // 5 + 720, // 6 + 5040, // 7 + 40320, // 8 + 362880, // 9 + 3628800, // 10 + 39916800, // 11 + 479001600, // 12 +}; + +unsigned long long fact(unsigned int num) { + if (num < 13) { + return FACT_TABLE[num]; + } + unsigned long long l = FACT_TABLE[12]; + for (unsigned int i = 12; i < num;) { + i++; + l *= i; + } + return l; +} diff --git a/libk/src/math/fclamp.c b/libk/src/math/fclamp.c new file mode 100644 index 0000000..f757b48 --- /dev/null +++ b/libk/src/math/fclamp.c @@ -0,0 +1,13 @@ +#include <math.h> + +double fclamp(double x, double l, double h) { + if (x < l) return l; + if (x > h) return h; + return x; +} + +float fclampf(float x, float l, float h) { + if (x < l) return l; + if (x > h) return h; + return x; +} diff --git a/libk/src/math/floor.c b/libk/src/math/floor.c new file mode 100644 index 0000000..ce8e07e --- /dev/null +++ b/libk/src/math/floor.c @@ -0,0 +1,55 @@ +#include <stdint.h> +#include <float.h> +#include <math.h> + +#include "internal/libm.h" + +#define EPS DBL_EPSILON + +static const double toint = 1/EPS; + +double floor(double x) { + union {double f; uint64_t i;} u = {x}; + int e = u.i >> 52 & 0x7ff; + double y; + + if (e >= 0x3ff+52 || x == 0) + return x; + if (u.i >> 63) + y = x - toint + toint - x; + else + y = x + toint - toint - x; + if (e <= 0x3ff-1) { + return u.i >> 63 ? -1 : 0; + } + if (y > 0) { + FORCE_EVAL(y); + return x + y - 1; + } + return x + y; +} + +float floorf(float x) { + union {float f; uint32_t i;} u = {x}; + int e = (int)(u.i >> 23 & 0xff) - 0x7f; + uint32_t m; + + if (e >= 23) + return x; + if (e >= 0) { + m = 0x007fffff >> e; + if ((u.i & m) == 0) + return x; + FORCE_EVAL(x + 0x1p120f); + if (u.i >> 31) + u.i += m; + u.i &= ~m; + } else { + FORCE_EVAL(x + 0x1p120f); + if (u.i >> 31 == 0) + u.i = 0; + else if (u.i << 1) + u.f = -1.0; + } + return u.f; +} diff --git a/libk/src/math/fma.c b/libk/src/math/fma.c new file mode 100644 index 0000000..b26229e --- /dev/null +++ b/libk/src/math/fma.c @@ -0,0 +1,38 @@ +#include <stdint.h> +#include <math.h> + +double fma(double x, double y, double z) { + double xy, result; + union {double f; uint64_t i;} u; + int e; + + xy = (double)x * y; + result = xy + z; + u.f = result; + e = u.i>>52 & 0x7ff; + if ( + (u.i & 0x1fffffff) != 0x10000000 || + e == 0x7ff || + (result - xy == z && result - z == xy) + ) { + z = result; + return z; + } + + double err; + int neg = u.i >> 63; + if (neg == (z > xy)) + err = xy - result + z; + else + err = z - result + xy; + if (neg == (err < 0)) + u.i++; + else + u.i--; + z = u.f; + return z; +} + +float fmaf(float x, float y, float z) { + return fma(x, y, z); +} diff --git a/libk/src/math/fmod.c b/libk/src/math/fmod.c new file mode 100644 index 0000000..996f78b --- /dev/null +++ b/libk/src/math/fmod.c @@ -0,0 +1,129 @@ +#include <math.h> +#include <stdint.h> + +double fmod(double x, double y) { + union {double f; uint64_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>52 & 0x7ff; + int ey = uy.i>>52 & 0x7ff; + int sx = ux.i>>63; + uint64_t i; + + /* in the followings uxi should be ux.i, but then gcc wrongly adds */ + /* float load/store to inner loops ruining performance and code size */ + uint64_t uxi = ux.i; + + if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) + return (x*y)/(x*y); + if (uxi<<1 <= uy.i<<1) { + if (uxi<<1 == uy.i<<1) + return 0*x; + return x; + } + + /* normalize x and y */ + if (!ex) { + for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1ULL >> 12; + uxi |= 1ULL << 52; + } + if (!ey) { + for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1ULL >> 12; + uy.i |= 1ULL << 52; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 63 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + uxi <<= 1; + } + i = uxi - uy.i; + if (i >> 63 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + for (; uxi>>52 == 0; uxi <<= 1, ex--); + + /* scale result */ + if (ex > 0) { + uxi -= 1ULL << 52; + uxi |= (uint64_t)ex << 52; + } else { + uxi >>= -ex + 1; + } + uxi |= (uint64_t)sx << 63; + ux.i = uxi; + return ux.f; +} + +float fmodf(float x, float y) { + union {float f; uint32_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>23 & 0xff; + int ey = uy.i>>23 & 0xff; + uint32_t sx = ux.i & 0x80000000; + uint32_t i; + uint32_t uxi = ux.i; + + if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) + return (x*y)/(x*y); + if (uxi<<1 <= uy.i<<1) { + if (uxi<<1 == uy.i<<1) + return 0*x; + return x; + } + + /* normalize x and y */ + if (!ex) { + for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1U >> 9; + uxi |= 1U << 23; + } + if (!ey) { + for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1U >> 9; + uy.i |= 1U << 23; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 31 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + uxi <<= 1; + } + i = uxi - uy.i; + if (i >> 31 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + for (; uxi>>23 == 0; uxi <<= 1, ex--); + + /* scale result up */ + if (ex > 0) { + uxi -= 1U << 23; + uxi |= (uint32_t)ex << 23; + } else { + uxi >>= -ex + 1; + } + uxi |= sx; + ux.i = uxi; + return ux.f; +} diff --git a/libk/src/math/frexp.c b/libk/src/math/frexp.c new file mode 100644 index 0000000..16b8dd3 --- /dev/null +++ b/libk/src/math/frexp.c @@ -0,0 +1,19 @@ +#include <math.h> + +double frexp(double arg, int* exp) { + *exp = 0; + while (arg > 1) { + arg /= 2;; + (*exp)++; + } + return arg; +} + +float frexpf(float arg, int* exp) { + *exp = 0; + while (arg > 1) { + arg /= 2; + (*exp)++; + } + return arg; +} diff --git a/libk/src/math/pow.c b/libk/src/math/pow.c new file mode 100644 index 0000000..c850db7 --- /dev/null +++ b/libk/src/math/pow.c @@ -0,0 +1,152 @@ +#include <stdint.h> +#include <string.h> +#include <math.h> + +uint32_t float_as_uint32 (float a) { + uint32_t r; + memcpy (&r, &a, sizeof r); + return r; +} + +float uint32_as_float (uint32_t a) { + float r; + memcpy (&r, &a, sizeof r); + return r; +} + +void logf_ext (float a, float *loghi, float *loglo) { + const float LOG2_HI = 6.93147182e-1f; + const float LOG2_LO = -1.90465421e-9f; + const float SQRT_HALF = 0.70710678f; + float m, r, i, s, t, p, qhi, qlo; + int e; + + const float POW_TWO_M23 = 1.19209290e-7f; + const float POW_TWO_P23 = 8388608.0f; + const float FP32_MIN_NORM = 1.175494351e-38f; + i = 0.0f; + + if (a < FP32_MIN_NORM) { + a = a * POW_TWO_P23; + i = -23.0f; + } + + e = (float_as_uint32 (a) - float_as_uint32 (SQRT_HALF)) & 0xff800000; + m = uint32_as_float (float_as_uint32 (a) - e); + i = fmaf ((float)e, POW_TWO_M23, i); + + p = m + 1.0f; + m = m - 1.0f; + r = 1.0f / p; + qhi = r * m; + qlo = r * fmaf (qhi, -m, fmaf (qhi, -2.0f, m)); + + s = qhi * qhi; + r = 0.1293334961f; + r = fmaf (r, s, 0.1419928074f); + r = fmaf (r, s, 0.2000148296f); + r = fmaf (r, s, 0.3333332539f); + t = fmaf (qhi, qlo + qlo, fmaf (qhi, qhi, -s)); + p = s * qhi; + t = fmaf (s, qlo, fmaf (t, qhi, fmaf (s, qhi, -p))); + s = fmaf (r, p, fmaf (r, t, qlo)); + r = 2 * qhi; + + t = fmaf ( LOG2_HI, i, r); + p = fmaf (-LOG2_HI, i, t); + s = fmaf ( LOG2_LO, i, fmaf (2.f, s, r - p)); + *loghi = p = t + s; + *loglo = (t - p) + s; +} + +float expf_unchecked (float a) { + float f, j, r; + int i; + + j = fmaf (1.442695f, a, 12582912.f) - 12582912.f; + f = fmaf (j, -6.93145752e-1f, a); + f = fmaf (j, -1.42860677e-6f, f); + i = (int)j; + + r = 1.37805939e-3f; + r = fmaf (r, f, 8.37312452e-3f); + r = fmaf (r, f, 4.16695364e-2f); + r = fmaf (r, f, 1.66664720e-1f); + r = fmaf (r, f, 4.99999851e-1f); + r = fmaf (r, f, 1.00000000e+0f); + r = fmaf (r, f, 1.00000000e+0f); + + float s, t; + uint32_t ia = (i > 0) ? 0u : 0x83000000u; + s = uint32_as_float (0x7f000000u + ia); + t = uint32_as_float (((uint32_t)i << 23) - ia); + r = r * s; + r = r * t; + + return r; +} + +float powf_core (float a, float b) { + const float MAX_IEEE754_FLT = uint32_as_float (0x7f7fffff); + const float EXP_OVFL_BOUND = 88.7228394f; // 0x1.62e430p+6f; + const float EXP_OVFL_UNFL_F = 104.0f; + const float MY_INF_F = uint32_as_float (0x7f800000); + float lhi, llo, thi, tlo, phi, plo, r; + + logf_ext (a, &lhi, &llo); + + thi = lhi * b; + + if (fabsf (thi) > EXP_OVFL_UNFL_F) { + r = (thi < 0.0f) ? 0.0f : MY_INF_F; + } else { + tlo = fmaf (lhi, b, -thi); + tlo = fmaf (llo, b, +tlo); + phi = thi + tlo; + + if (phi == EXP_OVFL_BOUND) + phi = uint32_as_float (float_as_uint32 (phi) - 1); + + plo = (thi - phi) + tlo; + r = expf_unchecked (phi); + if (fabsf (r) <= MAX_IEEE754_FLT) { + r = fmaf (plo, r, r); + } + } + return r; +} + +float powf (float a, float b) { + const float MY_INF_F = uint32_as_float (0x7f800000); + const float MY_NAN_F = uint32_as_float (0xffc00000); + int expo_odd_int; + float r; + + expo_odd_int = fmaf (-2.0f, floorf (0.5f * b), b) == 1.0f; + if ((a == 1.0f) || (b == 0.0f)) { + r = 1.0f; + } else if (isnan (a) || isnan (b)) { + r = a + b; + } else if (isinf (b)) { + r = ((fabsf (a) < 1.0f) != (b < 0.0f)) ? 0.0f : MY_INF_F; + if (a == -1.0f) r = 1.0f; + } else if (isinf (a)) { + r = (b < 0.0f) ? 0.0f : MY_INF_F; + if ((a < 0.0f) && expo_odd_int) r = -r; + } else if (a == 0.0f) { + r = (expo_odd_int) ? (a + a) : 0.0f; + if (b < 0.0f) r = copysignf (MY_INF_F, r); + } else if ((a < 0.0f) && (b != floorf (b))) { + r = MY_NAN_F; + } else { + r = powf_core (fabsf (a), b); + if ((a < 0.0f) && expo_odd_int) { + r = -r; + } + } + return r; +} + +double pow (double a, double b) { + return powf(a, b); // who cares about precision in a kernel :3 +} diff --git a/libk/src/math/sqrt.c b/libk/src/math/sqrt.c new file mode 100644 index 0000000..b875079 --- /dev/null +++ b/libk/src/math/sqrt.c @@ -0,0 +1,36 @@ +#include <math.h> + +float sqrtf(float num) { + if (num < 0) + return NAN; + + if (num < 2) + return num; + + float y = num; + float z = (y + (num / y)) / 2; + + while (fabsf(y - z) >= 0.00001) { + y = z; + z = (y + (num / y)) / 2; + } + return z; +} + +double sqrt(double num) { + if (num < 0) + return NAN; + + if (num < 2) + return num; + + double y = num; + double z = (y + (num / y)) / 2; + + while (fabs(y - z) >= 0.00001) { + y = z; + z = (y + (num / y)) / 2; + } + return z; +} + diff --git a/libk/src/math/trig.c b/libk/src/math/trig.c new file mode 100644 index 0000000..f234d69 --- /dev/null +++ b/libk/src/math/trig.c @@ -0,0 +1,62 @@ +#include <math.h> + +double sin(double r) { + r = fmod(r + PI, PI * 2) - PI; + double d = r; + float mult = -1; + for (int i = 3; i < 11; i+= 2, mult = -mult) { + d += (pow(r, i)/fact(i)) * mult; + } + return d; +} + +double cos(double r) { + r = fmod(r + PI, PI * 2) - PI; + double d = 1; + float mult = -1; + for (int i = 2; i < 10; i+= 2, mult = -mult) { + d += (pow(r, i)/fact(i)) * mult; + } + return d; +} + +double tan(double r) { + return sin(r) / cos(r); +} + +double csc(double r) { + return 1 / sin(r); +} + +double sec(double r) { + return 1 / cos(r); +} + +double cot(double r) { + return cos(r) / sin(r); +} + +double sinh(double r) { + return (pow(E, r) - pow(E, -r)) / 2; +} + +double cosh(double r) { + return (pow(E, r) + pow(E, -r)) / 2; +} + +double tanh(double r) { + return sinh(r) / cosh(r); +} + +double csch(double r) { + return 1 / sinh(r); +} + +double sech(double r) { + return 1 / cosh(r); +} + +double coth(double r) { + return cosh(r) / sinh(r); +} + diff --git a/libk/src/stdlib.c b/libk/src/stdlib.c new file mode 100644 index 0000000..fb832ce --- /dev/null +++ b/libk/src/stdlib.c @@ -0,0 +1,164 @@ +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <ctype.h> + +#define ATOX(name, type) \ + type name(const char* s) { \ + for(; isspace(*s); s++); \ + int neg = 0; \ + switch (*s) { \ + case '-': \ + neg = 1; \ + /* FALLTHRU */ \ + case '+': \ + s++; \ + break; \ + } \ + type num = 0; \ + for (; *s == '0'; s++); \ + for (; isdigit(*s); s++) { \ + num *= 10; \ + num += *s - '0'; \ + } \ + return num * (neg ? -1 : 1); \ + } + +ATOX(atoi, int) +ATOX(atol, long int) +ATOX(atoll, long long int) + +char itoc(int i) { + if(i < 10) { + return '0' + i; + } else { + return 'a' + (i - 10); + } +} + +int ctoi(char c) { + if(c < 'A') { + return c - '0'; + } else if(c < 'a') { + return c - 'A' + 10; + } else { + return c - 'a' + 10; + } +} + +#define UXTOA(type, name) \ + char *name(unsigned type n, char *buffer, int radix) { \ + if (n == 0) { \ + buffer[0] = '0'; \ + buffer[1] = '\0'; \ + return buffer; \ + } \ + char *start = buffer; \ + for (; n; n /= radix) { \ + *buffer++ = itoc(n % radix); \ + } \ + *buffer-- = '\0'; \ + while(buffer > start) { \ + char tmp = *start; \ + *start++ = *buffer; \ + *buffer-- = tmp; \ + } \ + return buffer; \ + } + +UXTOA(int, utoa) +UXTOA(long int, ultoa) + +#define XTOA(type, name) \ + char *name(type n, char* buffer, int radix) { \ + if (n == 0) { \ + buffer[0] = '0'; \ + buffer[1] = '\0'; \ + return buffer; \ + } \ + if (n < 0) { \ + *buffer++ = '-'; \ + n = -n; \ + } \ + char *start = buffer; \ + for (; n; n /= radix) { \ + *buffer++ = itoc(n % radix); \ + } \ + *buffer-- = '\0'; \ + while(buffer > start) { \ + char tmp = *start; \ + *start++ = *buffer; \ + *buffer-- = tmp; \ + } \ + return buffer; \ + } + +XTOA(int, itoa) +XTOA(long int, ltoa) + +char *ftoa(float f, char *buffer) { + char *b = buffer; + if (f < 0 || f == -0) + *buffer++ = '-'; + int n, i=0, k=0; + n = (int) f; + while (n > 0) { + f /= 10; + n = (int)f; + i++; + } + *(buffer+i) = '.'; + f *= 10; + n = (int) f; + f -= n; + while ((n > 0.1) || (i > k)) { + if (k == i) + k++; + *(buffer+k) = '0' + n; + f *= 10; + n = (int) f; + f -= n; + k++; + } + *(buffer+k) = '\0'; + return b; +} + +#define STRTOX(name, type) \ + type name(const char *s, char **endptr, int radix) { \ + *endptr = NULL; \ + for(; isspace(*s); s++); \ + int neg = 0; \ + switch (*s) { \ + case '-': \ + neg = 1; \ + /* FALLTHRU */ \ + case '+': \ + s++; \ + break; \ + } \ + if (!radix) { \ + if (*s == '0') { \ + s++; \ + if (*s == 'x' || *s == 'X') { \ + s++; \ + radix = 16; \ + } else { \ + radix = 8; \ + } \ + } else { \ + radix = 10; \ + } \ + } \ + for (; *s == '0'; s++, *endptr = (void*) s); \ + type num = 0; \ + for (; isdigit(*s); s++, *endptr = (void*) s) { \ + num *= radix; \ + num += *s - '0'; \ + } \ + return num * (neg ? -1 : 1); \ + } + +STRTOX(strtoi, int) +STRTOX(strtol, long int) +STRTOX(strtoll, long long int) diff --git a/libk/src/string.c b/libk/src/string.c new file mode 100644 index 0000000..6dfa683 --- /dev/null +++ b/libk/src/string.c @@ -0,0 +1,61 @@ +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +int memcmp(const void *vl, const void *vr, size_t n) { + const unsigned char *l = vl, *r = vr; + for (; n && *l == *r; n--, l++, r++); + return n ? *l-*r : 0; +} + +void *memcpy(void *restrict dest, const void *restrict src, size_t n) { + char *d = dest; + const char *s = src; + for (; n; n--) *d++ = *s++; + return dest; +} + +void *memmove(void *dest, const void *src, size_t n) { + char *d = dest; + const char *s = src; + + if (d==s) return d; + + if (d<s) { + for (; n; n--) *d++ = *s++; + } else { + while (n) n--, d[n] = s[n]; + } + + return dest; +} + +void *memset(void *dest, int c, size_t n) { + unsigned char *d = dest; + for (; n; n--) *d++ = c; + return dest; +} + +char *strcpy(char *restrict dest, const char *restrict src) { + for(; (*dest = *src); dest++, src++); + return dest; +} + +char *strncpy(char *restrict dest, const char *restrict src, size_t n) { + for(; (*dest = *src) && n; dest++, src++, n--); + memset(dest, 0, n); + return dest; +} + +size_t strlen(const char *s) { + size_t len = 0; + for(; *s; s++, len++); + return len; +} + +int strncmp(const char* lhs, const char* rhs, size_t n) { + const unsigned char *l=(void *)lhs, *r=(void *)rhs; + if (!n--) return 0; + for (; *l && *r && n && *l == *r ; l++, r++, n--); + return *l - *r; +} |