diff options
author | 2015-01-31 20:35:30 +0200 | |
---|---|---|
committer | 2015-03-03 23:36:16 +0200 | |
commit | 8b26e3ef33e3871762ebd62acbff85b2c3abd9fc (patch) | |
tree | 67d917b8694572b735662d2786fb77eac23ccaa9 /src | |
download | librin-b3a66e31520a5dd2a8f95827aa42ce6c4b7933a0.tar.gz librin-b3a66e31520a5dd2a8f95827aa42ce6c4b7933a0.tar.bz2 librin-b3a66e31520a5dd2a8f95827aa42ce6c4b7933a0.zip |
Initial commit - Release 0.0.1librin-0.0.1
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 42 | ||||
-rw-r--r-- | src/diagnostic/Makefile.am | 27 | ||||
-rw-r--r-- | src/diagnostic/diagnostic.c | 59 | ||||
-rw-r--r-- | src/diagnostic/diagnostic_private.h | 29 | ||||
-rw-r--r-- | src/dummy.c | 0 | ||||
-rw-r--r-- | src/float/Makefile.am | 26 | ||||
-rw-r--r-- | src/float/float.c | 248 | ||||
-rw-r--r-- | src/float/float_private.h | 29 |
8 files changed, 460 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..3b8b43c --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,42 @@ +# Copyright (C) 2015 Gediminas Jakutis +# +# This Makefile.am is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; version 2.1 +# of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +SUBDIRS = float diagnostic + +AM_CFLAGS = \ + -I$(top_srcdir)/include/ \ + -Wall \ + -Wextra + +RIN_VER_MAJOR = 0 +RIN_VER_MINOR = 0 +RIN_VER_PATCH = 0 + +lib_LTLIBRARIES = librin.la + +librin_la_LDFLAGS = -version-info $(RIN_VER_MAJOR):$(RIN_VER_MINOR):$(RIN_VER_PATCH) + +librin_la_SOURCES = dummy.c + +librin_la_LIBADD = \ + float/librin_float.la \ + diagnostic/librin_diagnostic.la + +librin_includedir = $(includedir)/rin +librin_include_HEADERS = \ + $(top_srcdir)/include/rin/float.h \ + $(top_srcdir)/include/rin/float_types.h \ + $(top_srcdir)/include/rin/diagnostic.h diff --git a/src/diagnostic/Makefile.am b/src/diagnostic/Makefile.am new file mode 100644 index 0000000..8787230 --- /dev/null +++ b/src/diagnostic/Makefile.am @@ -0,0 +1,27 @@ + +# Copyright (C) 2015 Gediminas Jakutis +# +# This Makefile.am is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; version 2.1 +# of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +AM_CFLAGS = \ + -I$(top_srcdir)/include/ \ + -Wall \ + -Wextra + +noinst_LTLIBRARIES = librin_diagnostic.la + +librin_diagnostic_la_SOURCES = \ + diagnostic.c \ + diagnostic_private.h diff --git a/src/diagnostic/diagnostic.c b/src/diagnostic/diagnostic.c new file mode 100644 index 0000000..0648abe --- /dev/null +++ b/src/diagnostic/diagnostic.c @@ -0,0 +1,59 @@ +/* + * The Rin Library – diagnostics module + * + * Copyright (C) 2015 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "diagnostic_private.h" + +void rin_err(const char *format, ...) +{ + va_list args; + + va_start(args, format); + __rin_msg(stderr, "error", format, args); +} + +void rin_warn(const char *format, ...) +{ + va_list args; + + va_start(args, format); + __rin_msg(stderr, "warning", format, args); +} + +void rin_fixme(const char *format, ...) +{ + va_list args; + + va_start(args, format); + __rin_msg(stderr, "fixme", format, args); +} + +void rin_info(const char *format, ...) +{ + va_list args; + + va_start(args, format); + __rin_msg(stdout, "info", format, args); +} + +static void __rin_msg(FILE *stream, const char *prefix, const char *format, va_list args) +{ + fprintf(stream, "%s: ", prefix); + vfprintf(stream, format, args); +} diff --git a/src/diagnostic/diagnostic_private.h b/src/diagnostic/diagnostic_private.h new file mode 100644 index 0000000..284d2e7 --- /dev/null +++ b/src/diagnostic/diagnostic_private.h @@ -0,0 +1,29 @@ +/* + * The Rin Library – diagnostics module + * + * Copyright (C) 2015 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBRIN_DIAGNOSTIC_PRIVATE_INCLUDED +#define LIBRIN_DIAGNOSTIC_PRIVATE_INCLUDED + +#include <stdio.h> +#include <stdarg.h> + +static void __rin_msg(FILE *stream, const char *prefix, const char *format, va_list args); + +#endif /* LIBRIN_DIAGNOSTIC_PRIVATE_INCLUDED */ diff --git a/src/dummy.c b/src/dummy.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/dummy.c diff --git a/src/float/Makefile.am b/src/float/Makefile.am new file mode 100644 index 0000000..d8d2675 --- /dev/null +++ b/src/float/Makefile.am @@ -0,0 +1,26 @@ +# Copyright (C) 2015 Gediminas Jakutis +# +# This Makefile.am is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; version 2.1 +# of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +AM_CFLAGS = \ + -I$(top_srcdir)/include/ \ + -Wall \ + -Wextra + +noinst_LTLIBRARIES = librin_float.la + +librin_float_la_SOURCES = \ + float.c \ + float_private.h diff --git a/src/float/float.c b/src/float/float.c new file mode 100644 index 0000000..97fcb41 --- /dev/null +++ b/src/float/float.c @@ -0,0 +1,248 @@ +/* + * The Rin Library – floating point module + * + * Copyright (C) 2015 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "rin/float.h" +#include "rin/float_types.h" +#include "float_private.h" + +/* + * TODO: + * · Doxygen-ize comments + * · Diagnostics + * · moar portability + * · ?? + */ + +/* + * signbit functions return the sign bit of a floating point number + * in the position where it is found on the raw float data itself. + * Set sign bit means it is negative + */ +uint32_t rin_signbitf(const float num) +{ + uint32_t ret; + ret = rin_float_to_uint(num); + return ret & 0x80000000u; +} + +uint64_t rin_signbitd(const double num) +{ + uint64_t ret; + ret = rin_double_to_ulong(num); + return ret & 0x8000000000000000ull; +} + +/* + * hexstring functions format a string of the hexidecimal representation + * of the raw floating point number data + * + * str has to point to enough memory to hold the said string + * + * mode hold modebits. Has to be either RIN_HEXSTRING_DEFAULT or any of + * the available modes ORed togther. + * Only one non-default mode is available at the moment. + */ + +char *rin_float_to_hexstring(const float num, char *str, unsigned int mode) +{ + char buffer[16] = { '\0' }; + uint32_t tmp; + size_t ccnt; + + tmp = rin_float_to_uint(num); + ccnt = sprintf(buffer, "%x", tmp); + + if (mode & RIN_HEXSTRING_NOPREFIX) { + memcpy(str, "00000000", 9); + memcpy(&str[8 - ccnt], buffer, ccnt); + } else { + memcpy(str, "0x00000000", 11); + memcpy(&str[10 - ccnt], buffer, ccnt); + } + + return str; +} + +char *rin_double_to_hexstring(const double num, char *str, unsigned int mode) +{ + char buffer[32] = { '\0' }; + uint64_t tmp; + size_t ccnt; + + tmp = rin_double_to_ulong(num); + ccnt = sprintf(buffer, "%lx", tmp); + + if (mode & RIN_HEXSTRING_NOPREFIX) { + memcpy(str, "0000000000000000", 17); + memcpy(&str[16 - ccnt], buffer, ccnt); + } else { + memcpy(str, "0x0000000000000000", 19); + memcpy(&str[18 - ccnt], buffer, ccnt); + } + + return str; +} + +/* + * These comparison functions use Units In Last Place (ULPs) to check if the numbers + * are close enough to be considered equal, which addresses most shortcomings of + * epsilon-based comparison. + * + * TODO: Still not implemented optimally and can produce results worse than epsilon + * comparison in some situations. + */ + +unsigned int rin_compare_float(const float a, const float b, uint32_t max_ulps) +{ + /* in case signs differ, "regular" comparison makes no sense */ + if (rin_signbitf(a) != rin_signbitf(b)) { + /* unless it's a case of a signed zero, so check for that */ + if (a == b) { + return 0; + } else { + return 1; + } + } else { + return ((uint32_t) abs(rin_float_to_int(a) - rin_float_to_int(b))) > max_ulps; + } +} + +unsigned int rin_compare_vec2(const struct vec2 a, const struct vec2 b, uint32_t max_ulps) +{ + unsigned int ret; + + ret = rin_compare_float(a.x, b.x, max_ulps); + ret += rin_compare_float(a.y, b.y, max_ulps); + + return ret; +} + +unsigned int rin_compare_vec3(const struct vec3 a, const struct vec3 b, uint32_t max_ulps) +{ + unsigned int ret; + + ret = rin_compare_float(a.x, b.x, max_ulps); + ret += rin_compare_float(a.y, b.y, max_ulps); + ret += rin_compare_float(a.z, b.z, max_ulps); + + return ret; +} + +unsigned int rin_compare_vec4(const struct vec4 a, const struct vec4 b, uint32_t max_ulps) +{ + unsigned int ret; + + ret = rin_compare_float(a.x, b.x, max_ulps); + ret += rin_compare_float(a.y, b.y, max_ulps); + ret += rin_compare_float(a.z, b.z, max_ulps); + ret += rin_compare_float(a.w, b.w, max_ulps); + + return ret; +} + +unsigned int rin_compare_double(const double a, const double b, uint64_t max_ulps) +{ + /* in case signs differ, "regular" comparison makes no sense */ + if (rin_signbitd(a) != rin_signbitd(b)) { + /* unless it's a case of a signed zero, so check for that */ + if (a == b) { + return 0; + } else { + return 1; + } + } else { + return ((uint64_t) labs(rin_double_to_long(a) - rin_double_to_long(b))) > max_ulps; + } +} + +unsigned int rin_compare_vec2d(const struct vec2d a, const struct vec2d b, uint64_t max_ulps) +{ + unsigned int ret; + + ret = rin_compare_double(a.x, b.x, max_ulps); + ret += rin_compare_double(a.y, b.y, max_ulps); + + return ret; +} + +unsigned int rin_compare_vec3d(const struct vec3d a, const struct vec3d b, uint64_t max_ulps) +{ + unsigned int ret; + + ret = rin_compare_double(a.x, b.x, max_ulps); + ret += rin_compare_double(a.y, b.y, max_ulps); + ret += rin_compare_double(a.z, b.z, max_ulps); + + return ret; +} + +unsigned int rin_compare_vec4d(const struct vec4d a, const struct vec4d b, uint64_t max_ulps) +{ + unsigned int ret; + + ret = rin_compare_double(a.x, b.x, max_ulps); + ret += rin_compare_double(a.y, b.y, max_ulps); + ret += rin_compare_double(a.z, b.z, max_ulps); + ret += rin_compare_double(a.w, b.w, max_ulps); + + return ret; +} + +/* + * These [float_type]_to_[integer_type] functions do type punning in a + * standards-compliant / without invoking undefined behavior, which + * happens in most of the [sadly] widely used methods to do this. + */ + +uint32_t rin_float_to_uint(const float num) +{ + uint32_t ret; + + memcpy(&ret, &num, sizeof(num)); + + return ret; +} + +int32_t rin_float_to_int(const float num) +{ + int32_t ret; + + memcpy(&ret, &num, sizeof(num)); + + return ret; +} + +uint64_t rin_double_to_ulong(const double num) +{ + uint64_t ret; + + memcpy(&ret, &num, sizeof(num)); + + return ret; +} + +int64_t rin_double_to_long(const double num) +{ + int64_t ret; + + memcpy(&ret, &num, sizeof(num)); + + return ret; +} diff --git a/src/float/float_private.h b/src/float/float_private.h new file mode 100644 index 0000000..4eed70b --- /dev/null +++ b/src/float/float_private.h @@ -0,0 +1,29 @@ +/* + * The Rin Library – floating point module + * + * Copyright (C) 2015 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBRIN_FLOAT_PRIVATE_INCLUDED +#define LIBRIN_FLOAT_PRIVATE_INCLUDED + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> + +#endif /* LIBRIN_FLOAT_PRIVATE_INCLUDED */ |