summaryrefslogtreecommitdiff
path: root/libk
diff options
context:
space:
mode:
authorTyler Murphy <=>2023-07-16 02:54:32 -0400
committerTyler Murphy <=>2023-07-16 02:54:32 -0400
commitfbf131b5c043b27e0b1543374bb144e3e426f723 (patch)
tree07f0ab2fc107b36621d5ae95480e6a91e332548b /libk
downloadfinix-fbf131b5c043b27e0b1543374bb144e3e426f723.tar.gz
finix-fbf131b5c043b27e0b1543374bb144e3e426f723.tar.bz2
finix-fbf131b5c043b27e0b1543374bb144e3e426f723.zip
initial
Diffstat (limited to 'libk')
-rw-r--r--libk/Makefile20
-rw-r--r--libk/compile_flags.txt10
-rw-r--r--libk/include/ctype.h4
-rw-r--r--libk/include/math.h62
-rw-r--r--libk/include/stdlib.h25
-rw-r--r--libk/include/string.h13
-rw-r--r--libk/include/sys.h51
-rw-r--r--libk/src/ctype.c19
-rw-r--r--libk/src/internal/libm.h32
-rw-r--r--libk/src/math/abs.c14
-rw-r--r--libk/src/math/ceil.c59
-rw-r--r--libk/src/math/copysign.c20
-rw-r--r--libk/src/math/fact.c29
-rw-r--r--libk/src/math/fclamp.c13
-rw-r--r--libk/src/math/floor.c55
-rw-r--r--libk/src/math/fma.c38
-rw-r--r--libk/src/math/fmod.c129
-rw-r--r--libk/src/math/frexp.c19
-rw-r--r--libk/src/math/pow.c152
-rw-r--r--libk/src/math/sqrt.c36
-rw-r--r--libk/src/math/trig.c62
-rw-r--r--libk/src/stdlib.c164
-rw-r--r--libk/src/string.c61
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;
+}