aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/libc/conv.c182
-rw-r--r--libs/libc/inc/conv.h8
-rw-r--r--libs/libc/inc/def.h4
-rw-r--r--libs/libc/inc/math.h24
-rw-r--r--libs/libc/math.c72
-rw-r--r--libs/libc/print.c112
6 files changed, 209 insertions, 193 deletions
diff --git a/libs/libc/conv.c b/libs/libc/conv.c
index 668069c..64401ed 100644
--- a/libs/libc/conv.c
+++ b/libs/libc/conv.c
@@ -6,140 +6,104 @@
#include <mem.h>
#include <str.h>
-static const char HTOA_TABLE[] = "0123456789ABCDEF";
-static const char ITOA_TABLE[] = "0123456789";
-
-int atoi(const char *str)
+int itoa(int value, char *buffer, int base)
{
- u32 s_str = strlen(str);
- if (!s_str)
- return 0;
-
- u8 negative = 0;
- if (str[0] == '-')
- negative = 1;
+ char tmp[16];
+ char *tp = tmp;
+ int i;
+ unsigned v;
+
+ int sign = (base == 10 && value < 0);
+ if (sign)
+ v = -value;
+ else
+ v = (unsigned)value;
+
+ while (v || tp == tmp) {
+ i = v % base;
+ v /= base;
+ if (i < 10)
+ *tp++ = i + '0';
+ else
+ *tp++ = i + 'a' - 10;
+ }
- u32 i = 0;
- if (negative)
- i++;
+ int len = tp - tmp;
- int ret = 0;
- for (; i < s_str; i++) {
- ret += (str[i] - '0') * pow(10, (int)((s_str - i) - 1));
+ if (sign) {
+ *buffer++ = '-';
+ len++;
}
- if (negative)
- ret *= -1;
- return ret;
+ while (tp > tmp)
+ *buffer++ = *--tp;
+
+ return len;
}
-char *htoa(u32 n)
+static int normalize(f64 *val)
{
- char *ret = (char *)malloc(10);
+ int exp = 0;
+ double value = *val;
- int i = 0;
- while (n) {
- ret[i++] = HTOA_TABLE[n & 0xF];
- n >>= 4;
+ while (value >= 1.0) {
+ value /= 10.0;
+ ++exp;
}
- if (!i) {
- ret[0] = '0';
- i++;
+ while (value < 0.1) {
+ value *= 10.0;
+ --exp;
}
-
- for (; i <= 9; i++)
- ret[i] = 0;
-
- char *aux = strdup(ret);
- free(ret);
- ret = aux;
-
- strinv(ret);
- return ret;
+ *val = value;
+ return exp;
}
-int htoi(const char *str)
+#define FLOAT_WIDTH 5
+char *ftoa(f64 value, char *buffer)
{
- u32 s_str = strlen(str);
-
- u32 i = 0;
- int ret = 0;
- for (; i < s_str; i++) {
- char c = str[i];
- int aux = 0;
- if (c >= '0' && c <= '9')
- aux = c - '0';
- else if (c >= 'A' && c <= 'F')
- aux = (c - 'A') + 10;
-
- ret += aux * pow(16, (int)((s_str - i) - 1));
- }
+ int exp = 0;
+ u32 loc = 0;
- return ret;
-}
-
-char *itoa(int n)
-{
- if (!n) {
- char *ret = (char *)malloc(2);
- ret[0] = '0';
- ret[1] = 0;
- return ret;
+ if (value == 0.0) {
+ buffer[0] = '0';
+ buffer[1] = '\0';
+ return buffer;
}
- u8 negative = (u8)(n < 0);
- if (negative)
- n *= -1;
- int sz;
- for (sz = 0; n % pow(10, sz) != n; sz++) {
+ if (value < 0.0) {
+ *buffer++ = '-';
+ value = -value;
}
- char *ret = (char *)malloc((u32)(sz + 1));
+ exp = normalize(&value);
- for (int i = 0; i < sz; i++) {
- int digit = (n % pow(10, i + 1)) / pow(10, i);
- ret[i] = ITOA_TABLE[digit];
- }
- ret[sz] = 0;
-
- if (negative) {
- char *aux = (char *)malloc((u32)(sz + 2));
- strlcpy(aux, ret, sz + 2);
- aux[sz] = '-';
- aux[sz + 1] = 0;
- free(ret);
- ret = aux;
+ while (exp > 0) {
+ int digit = value * 10;
+ *buffer++ = digit + '0';
+ value = value * 10 - digit;
+ ++loc;
+ --exp;
}
- strinv(ret);
- return ret;
-}
+ if (loc == 0)
+ *buffer++ = '0';
-char *conv_base(int value, char *result, int base, int is_signed)
-{
- if (base < 2 || base > 36) {
- *result = '\0';
- return result;
+ *buffer++ = '.';
+
+ while (exp < 0 && loc < FLOAT_WIDTH) {
+ *buffer++ = '0';
+ --exp;
+ ++loc;
}
- char *ptr = result, *ptr1 = result;
- int tmp_value;
-
- do {
- tmp_value = value;
- value /= base;
- *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"
- [35 + (tmp_value - value * base)];
- } while (value);
-
- if (is_signed && tmp_value < 0)
- *ptr++ = '-';
- *ptr-- = '\0';
- while (ptr1 < ptr) {
- char tmp_char = *ptr;
- *ptr-- = *ptr1;
- *ptr1++ = tmp_char;
+ while (loc < FLOAT_WIDTH) {
+ int digit = value * 10.0;
+ *buffer++ = digit + '0';
+ value = value * 10.0 - digit;
+ ++loc;
}
- return result;
+ *buffer = '\0';
+
+ return buffer;
}
diff --git a/libs/libc/inc/conv.h b/libs/libc/inc/conv.h
index 95f7d02..8b88526 100644
--- a/libs/libc/inc/conv.h
+++ b/libs/libc/inc/conv.h
@@ -5,11 +5,7 @@
#include <def.h>
-int atoi(const char *str) NONNULL;
-char *htoa(u32 n);
-int htoi(const char *str) NONNULL;
-char *itoa(int n);
-
-char *conv_base(int value, char *result, int base, int is_signed) NONNULL;
+int itoa(int value, char *buffer, int base);
+char *ftoa(f64 value, char *buffer);
#endif
diff --git a/libs/libc/inc/def.h b/libs/libc/inc/def.h
index c9c89fd..3b173dd 100644
--- a/libs/libc/inc/def.h
+++ b/libs/libc/inc/def.h
@@ -19,6 +19,10 @@ typedef unsigned long u32;
typedef signed long long s64;
typedef unsigned long long u64;
+typedef float f32;
+typedef double f64;
+typedef long double f80;
+
/**
* Useful macros
*/
diff --git a/libs/libc/inc/math.h b/libs/libc/inc/math.h
index 82f431f..8affb72 100644
--- a/libs/libc/inc/math.h
+++ b/libs/libc/inc/math.h
@@ -3,6 +3,28 @@
#ifndef MATH_H
#define MATH_H
-int pow(int base, int exp);
+#include <def.h>
+
+/**
+ * Pi constants
+ */
+
+#define M_1_PI 0.31830988618379067154
+#define M_2_PI 0.63661977236758134308
+#define M_2_SQRTPI 1.12837916709551257390
+
+#define M_PI 3.14159265358979323846
+#define M_PI_2 1.57079632679489661923
+#define M_PI_4 0.78539816339744830962
+
+f64 pow(f64 base, f64 exp);
+f64 sqrt(f64 num);
+
+f32 sinf(f32 angle);
+f64 sin(f64 angle);
+f32 cosf(f32 angle);
+f64 cos(f64 angle);
+f32 tanf(f32 angle);
+f64 tan(f64 angle);
#endif
diff --git a/libs/libc/math.c b/libs/libc/math.c
index c8142b5..b84958b 100644
--- a/libs/libc/math.c
+++ b/libs/libc/math.c
@@ -2,16 +2,72 @@
#include <math.h>
-int pow(int base, int exp)
+f64 pow(f64 base, f64 exp)
{
- if (exp < 0)
- return 0;
+ f64 out;
+ __asm__ volatile("fyl2x;"
+ "fld %%st;"
+ "frndint;"
+ "fsub %%st,%%st(1);"
+ "fxch;"
+ "fchs;"
+ "f2xm1;"
+ "fld1;"
+ "faddp;"
+ "fxch;"
+ "fld1;"
+ "fscale;"
+ "fstp %%st(1);"
+ "fmulp;"
+ : "=t"(out)
+ : "0"(base), "u"(exp)
+ : "st(1)");
+ return out;
+}
+
+// TODO: More efficient sqrt?
+f64 sqrt(f64 num)
+{
+ return pow(num, .5);
+}
+
+/**
+ * Trigonometric functions
+ */
+
+f32 sinf(f32 angle)
+{
+ f32 ret = 0.0;
+ __asm__ volatile("fsin" : "=t"(ret) : "0"(angle));
+ return ret;
+}
- if (!exp)
- return 1;
+f64 sin(f64 angle)
+{
+ f64 ret = 0.0;
+ __asm__ volatile("fsin" : "=t"(ret) : "0"(angle));
+ return ret;
+}
+
+f32 cosf(f32 angle)
+{
+ return sinf(angle + (f32)M_PI_2);
+}
+
+f64 cos(f64 angle)
+{
+ return sin(angle + (f64)M_PI_2);
+}
+
+f32 tanf(f32 angle)
+{
+ return (f32)tan(angle);
+}
+
+f64 tan(f64 angle)
+{
+ f64 ret = 0.0, one;
+ __asm__ volatile("fptan" : "=t"(one), "=u"(ret) : "0"(angle));
- int ret = base;
- for (int i = 1; i < exp; i++)
- ret *= base;
return ret;
}
diff --git a/libs/libc/print.c b/libs/libc/print.c
index 2eb119a..da8ab25 100644
--- a/libs/libc/print.c
+++ b/libs/libc/print.c
@@ -16,82 +16,56 @@
#define WHT "\x1B[1;37m"
#define RES "\x1B[0m"
-static void append(char *dest, char *src, int index)
-{
- for (u32 i = index; i < strlen(src) + index; i++)
- dest[i] = src[i - index];
- dest[index + strlen(src)] = 0;
-}
-
int vsnprintf(char *str, u32 size, const char *format, va_list ap)
{
- u8 ready_to_format = 0;
-
- u32 i = 0;
- char buf = 0;
-
- // TODO: Fix format buffer overflow exploit
- char format_buffer[42] = { 0 };
-
- for (; *format; format++) {
- if (ready_to_format) {
- ready_to_format = 0;
-
- if (*format == '%') {
- str[i] = '%';
- continue;
- }
-
- buf = *format;
-
- // TODO: Improve this repetitive code
- if (buf == 's') {
- char *string = va_arg(ap, char *);
- assert(string);
- append(str, string, i);
- i = strlen(str);
- } else if (buf == 'x') {
- conv_base(va_arg(ap, u32), format_buffer, 16, 0);
- append(str, format_buffer, i);
- i = strlen(str);
- } else if (buf == 'd' || buf == 'i') {
- conv_base(va_arg(ap, s32), format_buffer, 10, 1);
- append(str, format_buffer, i);
- i = strlen(str);
- } else if (buf == 'u') {
- conv_base(va_arg(ap, u32), format_buffer, 10, 0);
- append(str, format_buffer, i);
- i = strlen(str);
- } else if (buf == 'o') {
- conv_base(va_arg(ap, u32), format_buffer, 8, 0);
- append(str, format_buffer, i);
- i = strlen(str);
- } else if (buf == 'b') {
- conv_base(va_arg(ap, u32), format_buffer, 2, 0);
- append(str, format_buffer, i);
- i = strlen(str);
- } else if (buf == 'c') {
- str[i] = (char)va_arg(ap, int);
- i++;
- } else {
- assert(0);
+ u32 length = 0;
+
+ int temp_int;
+ char temp_ch;
+ char *temp_str;
+ f64 temp_double;
+
+ char buffer[64] = { 0 };
+
+ char ch;
+ while ((ch = *format++)) {
+ if (ch == '%') {
+ switch (*format++) {
+ case '%':
+ str[length++] = '%';
+ break;
+ case 'c':
+ temp_ch = va_arg(ap, int);
+ str[length++] = temp_ch;
+ break;
+ case 's':
+ temp_str = va_arg(ap, char *);
+ length += strlcpy(&str[length], temp_str, size - length);
+ break;
+ case 'd':
+ temp_int = va_arg(ap, int);
+ itoa(temp_int, buffer, 10);
+ length += strlcpy(&str[length], buffer, size - length);
+ break;
+ case 'x':
+ temp_int = va_arg(ap, int);
+ itoa(temp_int, buffer, 16);
+ length += strlcpy(&str[length], buffer, size - length);
+ break;
+ case 'f':
+ temp_double = va_arg(ap, double);
+ ftoa(temp_double, buffer);
+ length += strlcpy(&str[length], buffer, size - length);
+ break;
+ default:
+ print("Unknown printf format\n");
}
} else {
- if (*format == '%')
- ready_to_format = 1;
- else {
- str[i] = *format;
- if (++i == size) {
- str[i] = 0;
- break;
- }
- }
+ str[length++] = ch;
}
-
- memset(format_buffer, 0, sizeof(format_buffer));
}
- return strlen(str);
+ return length;
}
int snprintf(char *str, u32 size, const char *format, ...)