summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--CHANGELOG.txt15
-rw-r--r--Makefile73
-rw-r--r--README.html64
-rw-r--r--test.cc151
-rw-r--r--zap/Makefile64
-rw-r--r--zap/include-priv/zap/priv.h11
-rw-r--r--zap/include/zap/base.h42
-rw-r--r--zap/include/zap/math.h94
-rw-r--r--zap/include/zap/mem.h59
-rw-r--r--zap/src/abs.c96
-rw-r--r--zap/src/fastimpl.c6
-rw-r--r--zap/src/fma.c171
-rw-r--r--zap/src/fndbyte.c19
-rw-r--r--zap/src/fndchr.c4
-rw-r--r--zap/src/foreach.c10
-rw-r--r--zap/src/memcmp.c8
-rw-r--r--zap/src/memcpy.c10
-rw-r--r--zap/src/memdup.c2
-rw-r--r--zap/src/memeq.c10
-rw-r--r--zap/src/memfill.c16
-rw-r--r--zap/src/strcmp.c4
-rw-r--r--zap/src/strcpy.c6
-rw-r--r--zap/src/strdup.c2
-rw-r--r--zap/src/streq.c4
-rw-r--r--zap/src/strfill.c4
-rw-r--r--zap/src/strlen.c4
27 files changed, 756 insertions, 194 deletions
diff --git a/.gitignore b/.gitignore
index 128428e..ca10573 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
*.a
*.o
-/build
/test
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 96d5b7c..6c1910f 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,3 +1,18 @@
+| F
+
+- Remove type specifier from version macro;
+- Add mathematical functions abs and fma;
+- Update documentation;
+- Remove nothrw attribute from foreach;
+- Remove UB from foreach test;
+- Fix parameter mismatch in foreach test;
+- Use unsigned char instead of uint_least8_t;
+- Remove unnecessary casts;
+- Add new headers: 'zap/math.h' (for mathematical functions), 'zap/mem.h' (for memory sequence functions);
+- Restructure makefile;
+- Fix not using INT_LEAST8_MAX and INT_LEAST8_MIN instead of INT8_MAX and INT8_MIN;
+- Remove '/build' from gitignore;
+
| E
- Fix incorrect version number;
diff --git a/Makefile b/Makefile
index 878dc3a..f4d59b1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,71 +1,20 @@
-# TOOLS
+LIBZAP = zap/libzap.a
-#CC = clang
+.PHONY: clean install purge zap
-# TOOL FLAGS
+zap:
+ $(MAKE) -Czap
-CFLAGS = \
- -Izap/include \
- -Izap/include-priv \
- -O3 \
- -fPIC \
- -g \
- -march=native \
- -std=c99 \
- -Wall \
- -Wextra \
- -Wpedantic
-
-# Uncomment to enable freestanding mode:
-#CFLAGS += \
- -Dzap_priv_nostdlib \
- -ffreestanding
-
-# Uncomment to disable assembly algorithms:
-#CFLAGS += -Dzap_priv_noasm
-
-# HEADERS
-
-HDRS = \
- zap/include-priv/zap/priv.h \
- zap/include/zap.h \
-
-# BINARIES
-
-OBJS = \
- zap/src/fastimpl.o \
- zap/src/fndbyte.o \
- zap/src/fndchr.o \
- zap/src/foreach.o \
- zap/src/memcmp.o \
- zap/src/memcpy.o \
- zap/src/memdup.o \
- zap/src/memeq.o \
- zap/src/memfill.o \
- zap/src/strcmp.o \
- zap/src/strdup.o \
- zap/src/streq.o \
- zap/src/strfill.o \
- zap/src/strcpy.o \
- zap/src/strlen.o
-
-LIB = libzap.a
-
-# TARGETS
-
-.PHONY: clean install purge
-
-$(LIB): $(OBJS)
- ar r $@ $(OBJS)
-
-install: $(LIB)
+install: zap
mkdir -pm755 $(HDRDIR)/zap
mkdir -pm755 $(LIBDIR)
install -Dm644 zap/include/zap/base.h $(HDRDIR)/zap
- install -Dm755 $(LIB) $(LIBDIR)/$(LIB)
+ install -Dm644 zap/include/zap/math.h $(HDRDIR)/zap
+ install -Dm644 zap/include/zap/mem.h $(HDRDIR)/zap
+ install -Dm755 $(LIBZAP) $(LIBDIR)
clean:
- rm -fr $(OBJS)
+ $(MAKE) -Czap clean
-purge: clean
- rm -fr $(LIB)
+purge:
+ $(MAKE) -Czap purge
diff --git a/README.html b/README.html
index d924e6d..1a08610 100644
--- a/README.html
+++ b/README.html
@@ -11,50 +11,90 @@
<p>The <i>install</i> target installs the headers to <i>$(HDRDIR)</i> and the library file to <i>$(LIBDIR)</i>.</p>
<p>Instructions for building the test program may be found on the first line of <i>test.c</i>.</p>
<h2>Documentation</h2>
+ <h3>abs</h3>
+ <h4>Synopsis</h4>
+ <code>#include &ltzap/math.h&gt<br />signed char zap_abs_c(signed char val);<br />int zap_abs_i(int val);<br />long zap_abs_l(long val);<br />long long zap_abs_ll(long long val);<br />short zap_abs_s(short val);</code>
+ <h4>Description</h4>
+ <p>Returns the absolute value of <i>val</i>.</p>
+ <br />
+ <h3>fma</h3>
+ <h4>Synopsis</h4>
+ <code>#include &ltzap/math.h&gt<br />signed char zap_fma_c(signed char a,signed char b,signed char c);<br/>int zap_fma_i(int a,int b,int c);<br/>long zap_fma_l(long a,long b,long c);<br/>long long zap_fma_ll(long long a,long long b,long long c);<br/>short zap_fma_s(short a,short b,short c);<br/>unsigned char zap_fma_uc(unsigned char a,unsigned char b,unsigned char c);<br/>unsigned int zap_fma_ui(unsigned int a,unsigned int b,unsigned int c);<br/>unsigned long zap_fma_ul( unsigned long a,unsigned long b,unsigned long c);<br/>unsigned long long zap_fma_ull(unsigned long long a,unsigned long long b,unsigned long long c);<br/>unsigned short zap_fma_us( unsigned short a,unsigned short b,unsigned short c);</code>
+ <h4>Description</h4>
+ <p>Returns the the fused multiply-add of <i>a</i>, <i>b</i>, and <i>c</i>.</p>
+ <br />
<h3>fndbyte</h3>
<h4>Synopsis</h4>
- <code>#include &ltzap/base.h&gt<br />size_t zap_fndbtyte(void const * ptr,size_t num,unsigned char byte);</code>
+ <code>#include &ltzap/mem.h&gt<br />size_t zap_fndbtyte(void const * ptr,size_t num,unsigned char byte);</code>
<h4>Description</h4>
<p>Searches for the byte-value <i>byte</i> in the array pointed to by <i>ptr</i> within the bounds of <i>num</i>.</p>
+ <p>If <i>ptr</i> is not a valid pointer to a null-terminated string, the behaviour is undefined.</p>
<p>If <i>num</i> is larger (but not smaller) than the number of bytes in the array, the behaviour is undefined.</p>
- <p>If the byte-value is found within the domain, the position of it's first occurrence (starting at zero) is returned. Otherwise <i>SIZE_MAX</i> is returned.</p>
+ <p>If the byte-value is found within the domain, the position of it's first occurrence (starting at zero) is returned. Otherwise, <i>SIZE_MAX</i> is returned.</p>
<br />
<h3>fndchr</h3>
<h4>Synopsis</h4>
- <code>#include &ltzap/base.h&gt<br />size_t zap_fndchr(char const * str,char chr);</code>
+ <code>#include &ltzap/mem.h&gt<br />size_t zap_fndchr(char const * str,char chr);</code>
<h4>Description</h4>
<p>Searches for the character <i>chr</i> in the string <i>str</i>.</p>
- <p>If the character is found in the string, the position of it's first occurrence (starting at zero) is returned. Otherwise <i>SIZE_MAX</i> is returned.</p>
+ <p>If the character is found in the string, the position of it's first occurrence (starting at zero) is returned. Otherwise, <i>SIZE_MAX</i> is returned.</p>
<p>If <i>str</i> is not a valid pointer to a null-terminated string, the behaviour is undefined.</p>
<br />
<h3>foreach</h3>
<h4>Synopsis</h4>
- <code>#include &ltzap/base.h&gt<br />void zap_foreach(void * ptr,size_t sz,size_t num,void (* fn)(void *));</code>
+ <code>#include &ltzap/mem.h&gt<br />void zap_foreach(void * ptr,size_t sz,size_t num,void (* fn)(void *),void * * rem);</code>
<h4>Description</h4>
- <p>Iterates through the array pointed to by <i>ptr</i>, invoking the function <i>fn</i> with a pointer to the current element. Each pointer is equal to the laster pointer plus <i>sz</i>.</p>
+ <p>Iterates through the array pointed to by <i>ptr</i>, invoking the function <i>fn</i> with a pointer to the current element. Each pointer value after the first is equal to the previous plus <i>sz</i>.</p>
+ <p>If the pointed-to object of <i>rem</i> is not a null pointer, the iterations are started from that address. If <i>fn</i> throws an exception, the current position is written to the pointed-to object of <i>rem</i> (unless <i>rem</i> is a null pointer) and <i>foreach</i> returns the control-flow to the caller via this exception.</p>
<p>If the expression <code>(sz * num)</code> is not a valid object size, the behaviour is undefined.</p>
- <p>If <i>fn</i> is not a valid function pointer, the behaviour is undefined.</p>
+ <p>If <i>fn</i> is not a valid pointer to a function with C language linkage, the behaviour is undefined.</p>
+ <p>If <i>rem</i> is not a null pointer and the pointed-to object is not initialised to <i>NULL</i> before the call to <i>foreach</i>, the behaviour is undefined.</p>
<br />
<h3>memcmp</h3>
<h4>Synopsis</h4>
- <code>#include &ltzap/base.h&gt<br />int_least8_t zap_memcmp(void const * lptr,size_t num,void const * rptr);</code>
+ <code>#include &ltzap/mem.h&gt<br />int_least8_t zap_memcmp(void const * lptr,size_t num,void const * rptr);</code>
<h4>Description</h4>
<p>Compares <i>num</i>-bytes of the arrays pointed to by <i>lptr</i> and <i>rptr</i>.</p>
<p>The returned value is determined by the first byte found to be different in the two arrays. If the byte has a larger value in <i>lptr</i>, a negative (less than zero) value is returned. If it's the other way, a positive (greater than zero) value is returned. Otherwise (the arrays where represented the same), zero is returned.</p>
<p>If <i>lptr</i> or <i>rptr</i> (or both) are not valid pointers to arrays, the behaviour is undefined.</p>
<p>If <i>num</i> is larger (but not smaller) than the number of bytes of the smallest array, the behaviour is undefined.</p>
<br />
+ <h3>memcpy</h3>
+ <h4>Synopsis</h4>
+ <code>#include &ltzap/mem.h&gt<br />void zap_memcpy(void const * in,size_t num,void * out);</code>
+ <h4>Description</h4>
+ <p>Copies <i>num</i>-bytes from the buffer pointed to by <i>in</i> into the same relative position in the buffer pointer to by <i>out</i>.</p>
+ <p>If <i>in</i> or <i>out</i> (or both) are not valid pointers to arrays, the behaviour is undefined.</p>
+ <p>If <i>num</i> is larger (but not smaller) than the number of bytes of the smallest array, the behaviour is undefined.</p>
+ <br />
<h3>memdup</h3>
<h4>Synopsis</h4>
- <code>#include &ltzap/base.h&gt<br />void * zap_memdup(void const * ptr,size_t num);</code>
+ <code>#include &ltzap/mem.h&gt<br />void * zap_memdup(void const * ptr,size_t num);</code>
<h4>Description</h4>
<p>Copies <i>num</i>-bytes from the array pointed to by <i>ptr</i> into a newly-allocated array. The new array is allocated by <i>malloc</i>.</p>
<p>The returned value is a pointer to the new array.</p>
<p>If <i>num</i> is larger (but not smaller) than the number of bytes in the array, the behaviour is undefined.</p>
<br />
+ <h3>memeq</h3>
+ <h4>Synopsis</h4>
+ <code>#include &ltzap/mem.h&gt<br />bool zap_memeq(void const * lptr,size_t num,void * rptr);</code>
+ <h4>Description</h4>
+ <p>Checks <i>num</i>-bytes of the buffers pointed to by <i>lptr</i> and <i>rptr</i> for equality.</p>
+ <p>If any two bytes are found to be different in the two buffers, false is returned. Otherwise, true is returned.</p>
+ <p>If <i>lptr</i> or <i>rptr</i> (or both) are not valid pointers to arrays, the behaviour is undefined.</p>
+ <p>If <i>num</i> is larger (but not smaller) than the number of bytes of the smallest array, the behaviour is undefined.</p>
+ <br />
+ <h3>memfill</h3>
+ <h4>Synopsis</h4>
+ <code>#include &ltzap/mem.h&gt<br />void zap_memfill(void const * ptr,size_t num,unsigned char byte);</code>
+ <h4>Description</h4>
+ <p>Fills <i>num</i>-bytes of the buffer pointed to by <i>ptr</i> with the representation of <i>byte</i>.</p>
+ <p>If <i>ptr</i> is not a valid pointer to an array, the behaviour is undefined.</p>
+ <p>If <i>num</i> is larger (but not smaller) than the number of bytes of in the array, the behaviour is undefined.</p>
+ <br />
<h3>streq</h3>
<h4>Synopsis</h4>
- <code>#include &ltzap/base.h&gt<br />_Bool zap_streq(char const * lstr,char const * rstr);</code>
+ <code>#include &ltzap/mem.h&gt<br />bool zap_streq(char const * lstr,char const * rstr);</code>
<h4>Description</h4>
<p>Checks the equality of the strings <i>lstr</i> and <i>rstr</i>.</p>
<p>If one of the strings has a length different from the other, or if any character in the two strings is different from the other (at the same offset), true is returned. Otherwise, false is returned.</p>
@@ -62,14 +102,14 @@
<br />
<h3>strfill</h3>
<h4>Synopsis</h4>
- <code>#include &ltzap/base.h&gt<br />void zap_strfill(char * str,char chr);</code>
+ <code>#include &ltzap/mem.h&gt<br />void zap_strfill(char * str,char chr);</code>
<h4>Description</h4>
<p>Writes the character <i>chr</i> to every valid position in the string <i>str</i>, excluding that of the null-terminator.</p>
<p>If <i>str</i> is not a valid pointer to a null-terminated string, the behaviour is undefined.</p>
<br />
<h3>strlen</h3>
<h4>Synopsis</h4>
- <code>#include &ltzap/base.h&gt<br />size_t zap_strlen(char const * str);</code>
+ <code>#include &ltzap/mem.h&gt<br />size_t zap_strlen(char const * str);</code>
<h4>Description</h4>
<p>Counts the number of characters in the string <i>str</i>.</p>
<p>Returns the number of characters (excluding the null-terminator) in the string.</p>
diff --git a/test.cc b/test.cc
index 8a181f9..521d556 100644
--- a/test.cc
+++ b/test.cc
@@ -1,11 +1,21 @@
-/* c++ -Izap/include -L. -otest test.cc -lzap */
+/* c++ -Izap/include -Lzap -otest test.cc -lzap */
#include <cassert>
#include <cinttypes>
#include <cstddef>
#include <cstdint>
#include <cstdio>
-#include <zap/base.h>
+#include <stdexcept>
+#include <zap/math.h>
+#include <zap/mem.h>
+
+extern "C" auto zap_test_foreachfn(void * const _ptr) -> void { /* This function is passed to foreach, which requires C-linkage function pointers. I tried to overload the function to also accept C++-linkage function pointers, but that only made GCC moan. */
+ auto const ptr {static_cast<int *>(_ptr)};
+ auto val {*ptr};
+ if (val == 0x45) {throw ::std::domain_error {"Damn!"};}
+ val %= 0x2;
+ *ptr = val;
+}
int main(void) {
::std::fprintf(stderr,"zap test\n");
@@ -13,16 +23,97 @@ int main(void) {
::std::fprintf(stderr,"fast: %s\n",::zap_fastimpl ? "yes" : "no");
::std::fprintf(stderr,"\n");
{
+ {
+ auto val {::zap_abs_c(-0x5D)};
+ ::std::fprintf(stderr,"val: %hhi\n",val);
+ assert(val == 0x5D);
+ }
+ {
+ auto val {::zap_abs_i(-0xEF4)};
+ ::std::fprintf(stderr,"val: %i\n",val);
+ assert(val == 0xEF4);
+ }
+ {
+ auto val {::zap_abs_l(-0x6666E67B)};
+ ::std::fprintf(stderr,"val: %li\n",val);
+ assert(val == 0x6666E67B);
+ }
+ {
+ auto val {::zap_abs_ll(-0x7C91A4B244F0DC99)};
+ ::std::fprintf(stderr,"val: %lli\n",val);
+ assert(val == 0x7C91A4B244F0DC99);
+ }
+ {
+ auto val {::zap_abs_s(-0xDC9)};
+ ::std::fprintf(stderr,"val: %i\n",val);
+ assert(val == 0xDC9);
+ }
+ }
+ ::std::fprintf(stderr,"\n");
+ {
+ { /* Largest number for each signed parameter: (floor(cbrt(2^(x-1)-1))) */
+ auto val {::zap_fma_c(0x5,0x2,0x2)};
+ ::std::fprintf(stderr,"val: %hhi\n",val);
+ assert(val == 0x9);
+ }
+ {
+ auto val {::zap_fma_i(0x29,0x4AD,0x453)};
+ ::std::fprintf(stderr,"val: %i\n",val);
+ assert(val == 0x143840);
+ }
+ {
+ auto val {::zap_fma_l(0x1BAA11,0x361DA,0x17462F)};
+ ::std::fprintf(stderr,"val: %li\n",val);
+ assert(val == 0x4EB8123D17);
+ }
+ {
+ auto val {::zap_fma_ll(0x45,0x60,0x1A4)};
+ ::std::fprintf(stderr,"val: %lli\n",val);
+ assert(val == 0x9DC5);
+ }
+ {
+ auto val {::zap_fma_s(0x7,0xE,0x1D)};
+ ::std::fprintf(stderr,"val: %i\n",val);
+ assert(val == 0x19D);
+ }
+ { /* Largest number for each unsigned parameter: (floor(cbrt(2^x-1))) */
+ auto val {::zap_fma_uc(0x6u,0x6u,0x3u)};
+ ::std::fprintf(stderr,"val: %hhu\n",val);
+ assert(val == 0x18u);
+ }
+ {
+ auto val {::zap_fma_ui(0x14u,0x17u,0x3u)};
+ ::std::fprintf(stderr,"val: %u\n",val);
+ assert(val == 0x59);
+ }
+ {
+ auto val {::zap_fma_ul(0x5AAu,0x412u,0x16Du)};
+ ::std::fprintf(stderr,"val: %lu\n",val);
+ assert(val == 0x5D354u);
+ }
+ {
+ auto val {::zap_fma_ull(0x10EFC7u,0x19FB63u,0x1133259u)};
+ ::std::fprintf(stderr,"val: %llu\n",val);
+ assert(val == 0x1BEE278BAB32u);
+ }
+ {
+ auto val {::zap_fma_us(0x23u,0x19u,0x1Cu)};
+ ::std::fprintf(stderr,"val: %u\n",val);
+ assert(val == 0x2DF);
+ }
+ }
+ ::std::fprintf(stderr,"\n");
+ {
constexpr ::std::size_t arrsz {0x8u};
::std::uint_least64_t arr0[arrsz] {0x0u};
::zap_memfill(arr0,arrsz * sizeof (::std::uint_least64_t),0x0u);
- ::std::fprintf(stderr,"arr0[0]: %" PRIX64 "\n",arr0[0x0u]);
- ::std::fprintf(stderr,"arr0[1]: %" PRIX64 "\n",arr0[0x1u]);
- ::std::fprintf(stderr,"arr0[2]: %" PRIX64 "\n",arr0[0x2u]);
- ::std::fprintf(stderr,"arr0[3]: %" PRIX64 "\n",arr0[0x3u]);
- ::std::fprintf(stderr,"arr0[4]: %" PRIX64 "\n",arr0[0x4u]);
- ::std::fprintf(stderr,"arr0[5]: %" PRIX64 "\n",arr0[0x5u]);
- ::std::fprintf(stderr,"arr0[6]: %" PRIX64 "\n",arr0[0x6u]);
+ ::std::fprintf(stderr,"arr0[0]: %" PRIXLEAST64 "\n",arr0[0x0u]);
+ ::std::fprintf(stderr,"arr0[1]: %" PRIXLEAST64 "\n",arr0[0x1u]);
+ ::std::fprintf(stderr,"arr0[2]: %" PRIXLEAST64 "\n",arr0[0x2u]);
+ ::std::fprintf(stderr,"arr0[3]: %" PRIXLEAST64 "\n",arr0[0x3u]);
+ ::std::fprintf(stderr,"arr0[4]: %" PRIXLEAST64 "\n",arr0[0x4u]);
+ ::std::fprintf(stderr,"arr0[5]: %" PRIXLEAST64 "\n",arr0[0x5u]);
+ ::std::fprintf(stderr,"arr0[6]: %" PRIXLEAST64 "\n",arr0[0x6u]);
assert(arr0[0x0u] == 0x0u);
assert(arr0[0x1u] == 0x0u);
assert(arr0[0x2u] == 0x0u);
@@ -31,13 +122,13 @@ int main(void) {
assert(arr0[0x5u] == 0x0u);
assert(arr0[0x6u] == 0x0u);
::zap_memfill(arr0,arrsz * sizeof (::std::uint_least64_t),0x7Fu);
- ::std::fprintf(stderr,"arr0[0]: %" PRIX64 "\n",arr0[0x0u]);
- ::std::fprintf(stderr,"arr0[1]: %" PRIX64 "\n",arr0[0x1u]);
- ::std::fprintf(stderr,"arr0[2]: %" PRIX64 "\n",arr0[0x2u]);
- ::std::fprintf(stderr,"arr0[3]: %" PRIX64 "\n",arr0[0x3u]);
- ::std::fprintf(stderr,"arr0[4]: %" PRIX64 "\n",arr0[0x4u]);
- ::std::fprintf(stderr,"arr0[5]: %" PRIX64 "\n",arr0[0x5u]);
- ::std::fprintf(stderr,"arr0[6]: %" PRIX64 "\n",arr0[0x6u]);
+ ::std::fprintf(stderr,"arr0[0]: %" PRIXLEAST64 "\n",arr0[0x0u]);
+ ::std::fprintf(stderr,"arr0[1]: %" PRIXLEAST64 "\n",arr0[0x1u]);
+ ::std::fprintf(stderr,"arr0[2]: %" PRIXLEAST64 "\n",arr0[0x2u]);
+ ::std::fprintf(stderr,"arr0[3]: %" PRIXLEAST64 "\n",arr0[0x3u]);
+ ::std::fprintf(stderr,"arr0[4]: %" PRIXLEAST64 "\n",arr0[0x4u]);
+ ::std::fprintf(stderr,"arr0[5]: %" PRIXLEAST64 "\n",arr0[0x5u]);
+ ::std::fprintf(stderr,"arr0[6]: %" PRIXLEAST64 "\n",arr0[0x6u]);
assert(arr0[0x0u] == 0x7F7F7F7F7F7F7F7Fu);
assert(arr0[0x1u] == 0x7F7F7F7F7F7F7F7Fu);
assert(arr0[0x2u] == 0x7F7F7F7F7F7F7F7Fu);
@@ -47,13 +138,13 @@ int main(void) {
assert(arr0[0x6u] == 0x7F7F7F7F7F7F7F7Fu);
::std::uint_least64_t arr1[arrsz] {0x0u};
::zap_memcpy(arr0,arrsz * sizeof (::std::uint_least64_t),arr1);
- ::std::fprintf(stderr,"arr1[0]: %" PRIX64 "\n",arr1[0x0u]);
- ::std::fprintf(stderr,"arr1[1]: %" PRIX64 "\n",arr1[0x1u]);
- ::std::fprintf(stderr,"arr1[2]: %" PRIX64 "\n",arr1[0x2u]);
- ::std::fprintf(stderr,"arr1[3]: %" PRIX64 "\n",arr1[0x3u]);
- ::std::fprintf(stderr,"arr1[4]: %" PRIX64 "\n",arr1[0x4u]);
- ::std::fprintf(stderr,"arr1[5]: %" PRIX64 "\n",arr1[0x5u]);
- ::std::fprintf(stderr,"arr1[6]: %" PRIX64 "\n",arr1[0x6u]);
+ ::std::fprintf(stderr,"arr1[0]: %" PRIXLEAST64 "\n",arr1[0x0u]);
+ ::std::fprintf(stderr,"arr1[1]: %" PRIXLEAST64 "\n",arr1[0x1u]);
+ ::std::fprintf(stderr,"arr1[2]: %" PRIXLEAST64 "\n",arr1[0x2u]);
+ ::std::fprintf(stderr,"arr1[3]: %" PRIXLEAST64 "\n",arr1[0x3u]);
+ ::std::fprintf(stderr,"arr1[4]: %" PRIXLEAST64 "\n",arr1[0x4u]);
+ ::std::fprintf(stderr,"arr1[5]: %" PRIXLEAST64 "\n",arr1[0x5u]);
+ ::std::fprintf(stderr,"arr1[6]: %" PRIXLEAST64 "\n",arr1[0x6u]);
assert(arr1[0x0u] == arr0[0x0u]);
assert(arr1[0x1u] == arr0[0x1u]);
assert(arr1[0x2u] == arr0[0x2u]);
@@ -80,7 +171,7 @@ int main(void) {
auto len {::zap_strlen(str)};
::std::fprintf(stderr,"len: %zX\n",len);
::std::size_t pos0 = ::zap_fndchr(str,' ');
- ::std::size_t pos1 = ::zap_fndbyte(str,len,(::std::uint_least8_t)' ');
+ ::std::size_t pos1 = ::zap_fndbyte(str,len,(unsigned char)' ');
::std::fprintf(stderr,"pos0: %zX\n",pos0);
::std::fprintf(stderr,"pos1: %zX\n",pos1);
assert(pos0 == 0x2u);
@@ -88,7 +179,7 @@ int main(void) {
str += pos0 + 0x1u;
len = ::zap_strlen(str);
pos0 = ::zap_fndchr(str,' ');
- pos1 = ::zap_fndbyte(str,len,(::std::uint_least8_t)' ');
+ pos1 = ::zap_fndbyte(str,len,(unsigned char)' ');
::std::fprintf(stderr,"pos0: %zX\n",pos0);
::std::fprintf(stderr,"pos1: %zX\n",pos1);
assert(pos0 == 0x2u);
@@ -96,7 +187,7 @@ int main(void) {
str += pos0 + 0x1u;
len = ::zap_strlen(str);
pos0 = ::zap_fndchr(str,' ');
- pos1 = ::zap_fndbyte(str,len,(::std::uint_least8_t)' ');
+ pos1 = ::zap_fndbyte(str,len,(unsigned char)' ');
::std::fprintf(stderr,"pos0: %zX\n",pos0);
::std::fprintf(stderr,"pos1: %zX\n",pos1);
assert(pos0 == SIZE_MAX);
@@ -163,12 +254,8 @@ int main(void) {
0x2,
0x3,
};
- ::zap_foreach(arr,sizeof (arr) / sizeof (int),sizeof (int),[](void * const _ptr) {
- auto const ptr {static_cast<int *>(_ptr)};
- auto val {*ptr};
- val %= 0x2;
- *ptr = val;
- });
+ void * rem {nullptr};
+ ::zap_foreach(arr,sizeof (int),sizeof (arr) / sizeof (int),::zap_test_foreachfn);
::std::fprintf(stderr,"arr[0]: %i\n",arr[0x0u]);
::std::fprintf(stderr,"arr[1]: %i\n",arr[0x1u]);
::std::fprintf(stderr,"arr[2]: %i\n",arr[0x2u]);
diff --git a/zap/Makefile b/zap/Makefile
new file mode 100644
index 0000000..b7db3dc
--- /dev/null
+++ b/zap/Makefile
@@ -0,0 +1,64 @@
+# TOOLS
+
+#CC = clang
+#CC = gcc
+
+# TOOL FLAGS
+
+CFLAGS = \
+ -Iinclude \
+ -Iinclude-priv \
+ -O3 \
+ -fPIC \
+ -g \
+ -march=native \
+ -std=c99 \
+ -Wall \
+ -Wextra \
+ -Wpedantic
+
+# ARTIFACTS
+
+OBJS = \
+ src/abs.o \
+ src/fastimpl.o \
+ src/fma.o \
+ src/fndbyte.o \
+ src/fndchr.o \
+ src/foreach.o \
+ src/memcmp.o \
+ src/memcpy.o \
+ src/memdup.o \
+ src/memeq.o \
+ src/memfill.o \
+ src/strcmp.o \
+ src/strdup.o \
+ src/streq.o \
+ src/strfill.o \
+ src/strcpy.o \
+ src/strlen.o
+
+LIB = libzap.a
+
+# OPTIONS
+
+# Uncomment to disable assembly algorithms:
+#CFLAGS += -Dzap_priv_noasm
+
+# Uncomment to enable freestanding mode (requries no runtime):
+#CFLAGS += \
+ -Dzap_priv_nostdlib \
+ -ffreestanding
+
+# TARGETS
+
+.PHONY: clean purge
+
+$(LIB): $(OBJS)
+ ar r $@ $(OBJS)
+
+clean:
+ rm -fr $(OBJS)
+
+purge: clean
+ rm -fr $(LIB)
diff --git a/zap/include-priv/zap/priv.h b/zap/include-priv/zap/priv.h
index 24718bb..8ebbd39 100644
--- a/zap/include-priv/zap/priv.h
+++ b/zap/include-priv/zap/priv.h
@@ -4,16 +4,15 @@
If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
-#if !defined(zap_hdr_priv)
-#define zap_hdr_priv
+#if !defined(zap_priv_hdr_priv)
+#define zap_priv_hdr_priv
#include <zap/base.h>
-#include <stddef.h>
-#include <stdint.h>
-
#if (defined(sus_comp_gnu) || defined(sus_comp_llvm)) && defined(sus_os_unix) && !defined(zap_priv_noasm) && (defined(sus_arch_amd64) || defined(sus_arch_ia32))
-#define zap_priv_fastimpl
+#define zap_priv_fastimpl (0x1u)
+#else
+#define zap_priv_fastimpl (0x0u)
#endif
#endif
diff --git a/zap/include/zap/base.h b/zap/include/zap/base.h
index 4866051..a52414b 100644
--- a/zap/include/zap/base.h
+++ b/zap/include/zap/base.h
@@ -5,31 +5,12 @@
*/
#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
#include <susinfo.h>
-#if !defined(zap_hdr_base)
-#define zap_hdr_base
+#if !defined(zap_priv_hdr_base)
+#define zap_priv_hdr_base
-#define zap_ver ((uint_Least64_t)0xEu)
-
-#if defined(sus_lang_asm)
-
-.extern zap_fndbyte
-.extern zap_fndchr
-.extern zap_foreach
-.extern zap_memcmp
-.extern zap_memcpy
-.extern zap_memeq
-.extern zap_memfill
-.extern zap_strcmp
-.extern zap_strcpy
-.extern zap_streq
-.extern zap_strfill
-.extern zap_strlen
-
-#else
+#define zap_ver (0xFu)
#if defined(sus_lang_cxx)
extern "C" {
@@ -37,23 +18,6 @@ extern "C" {
extern bool const zap_fastimpl;
-/* Memory sequence functions: */
-sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_fndbyte( void const * ptr, size_t num, unsigned char byte);
-sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_fndchr( char const * str, char chr);
-sus_attr_hot sus_attr_nothrw void zap_foreach( void * ptr, size_t sz, size_t num, void (* fn)(void *));
-sus_attr_hot sus_attr_nothrw sus_attr_useret int_least8_t zap_memcmp( void const * lstr,size_t num, void const * rstr);
-sus_attr_hot sus_attr_nothrw void zap_memcpy( void const * in, size_t num, void * out);
-sus_attr_alloc sus_attr_allocsz(0x2) sus_attr_hot sus_attr_nothrw sus_attr_useret void * zap_memdup( void const * ptr, size_t num);
-sus_attr_hot sus_attr_nothrw sus_attr_useret bool zap_memeq( void const * lptr,size_t num, void const * rptr);
-sus_attr_hot sus_attr_nothrw void zap_memfill( void * ptr, size_t num, unsigned char val);
-sus_attr_hot sus_attr_nothrw sus_attr_useret int_least8_t zap_strcmp( char const * lstr,char const * rstr);
-sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_strcpy( char const * in, char * out);
-sus_attr_alloc sus_attr_hot sus_attr_nothrw sus_attr_useret char * zap_strdup( char const * str);
-sus_attr_hot sus_attr_nothrw sus_attr_useret bool zap_streq( char const * lstr,char const * rstr);
-sus_attr_hot sus_attr_nothrw void zap_strfill( char * lstr,char chr);
-sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_strlen( char const * str);
-
-#endif
#if defined(sus_lang_cxx)
}
#endif
diff --git a/zap/include/zap/math.h b/zap/include/zap/math.h
new file mode 100644
index 0000000..97afb66
--- /dev/null
+++ b/zap/include/zap/math.h
@@ -0,0 +1,94 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/base.h>
+
+#include <susinfo.h>
+
+#if !defined(zap_priv_hdr_math)
+#define zap_priv_hdr_math
+
+#if !defined(sus_langfeat_c_llng) && !defined(sus_langfeat_cxx_llng)
+#error The (long long) type is required but unsupported by the implementation !
+#endif
+
+#if defined(sus_lang_cxx)
+extern "C" {
+#endif
+
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret signed char zap_abs_c( signed char val);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret int zap_abs_i( int val);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret long zap_abs_l( long val);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret long long zap_abs_ll( long long val);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret short zap_abs_s( short val);
+
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret signed char zap_fma_c( signed char a,signed char b,signed char c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret int zap_fma_i( int a,int b,int c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret long zap_fma_l( long a,long b,long c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret long long zap_fma_ll( long long a,long long b,long long c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret short zap_fma_s( short a,short b,short c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned char zap_fma_uc( unsigned char a,unsigned char b,unsigned char c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned int zap_fma_ui( unsigned int a,unsigned int b,unsigned int c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned long zap_fma_ul( unsigned long a,unsigned long b,unsigned long c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned long long zap_fma_ull(unsigned long long a,unsigned long long b,unsigned long long c);
+sus_attr_const sus_attr_hot sus_attr_nothrw sus_attr_useret unsigned short zap_fma_us( unsigned short a,unsigned short b,unsigned short c);
+
+#if defined(sus_langfeat_c_generic)
+
+#define zap_abs_tg(_val) \
+ (_Generic((_val), \
+ signed char:zap_abs_c, \
+ int: zap_abs_i, \
+ long: zap_abs_l, \
+ long long: zap_abs_ll,\
+ short: zap_abs_s, \
+ )((_val)))
+
+#define zap_fma_tg(_a,_b,_c) \
+ (_Generic((_a), \
+ signed char: zap_fma_c, \
+ int: zap_fma_i, \
+ long: zap_fma_l, \
+ long long: zap_fma_ll, \
+ short: zap_fma_s, \
+ unsigned char: zap_fma_uc, \
+ unsigned int: zap_fma_ui, \
+ unsigned long: zap_fma_ul, \
+ unsigned long long:zap_fma_ull,\
+ unsigned short: zap_fma_us, \
+ )((_a),(_b),(_c)))
+
+#elif defined(sus_lang_cxx)
+
+extern "C++" {
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline signed char zap_priv_cxxtg_abs(signed char const _val) {return ::zap_abs_c( _val);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline int zap_priv_cxxtg_abs(int const _val) {return ::zap_abs_i( _val);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline long zap_priv_cxxtg_abs(long const _val) {return ::zap_abs_l( _val);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline long long zap_priv_cxxtg_abs(long long const _val) {return ::zap_abs_ll(_val);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline short zap_priv_cxxtg_abs(short const _val) {return ::zap_abs_s( _val);};
+
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline signed char zap_priv_cxxtg_fma(signed char const _a,signed char const _b,signed char const _c) {return ::zap_fma_c( _a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline int zap_priv_cxxtg_fma(int const _a,int const _b,int const _c) {return ::zap_fma_i( _a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline long zap_priv_cxxtg_fma(long const _a,long const _b,long const _c) {return ::zap_fma_l( _a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline long long zap_priv_cxxtg_fma(long long const _a,long long const _b,long long const _c) {return ::zap_fma_ll( _a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline short zap_priv_cxxtg_fma(short const _a,short const _b,short const _c) {return ::zap_fma_s( _a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned char zap_priv_cxxtg_fma(unsigned char const _a,unsigned char const _b,unsigned char const _c) {return ::zap_fma_uc( _a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned int zap_priv_cxxtg_fma(unsigned int const _a,unsigned int const _b,unsigned int const _c) {return ::zap_fma_ui( _a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned long zap_priv_cxxtg_fma(unsigned long const _a,unsigned long const _b,unsigned long const _c) {return ::zap_fma_ul( _a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned long long zap_priv_cxxtg_fma(unsigned long long const _a,unsigned long long const _b,unsigned long long const _c) {return ::zap_fma_ull(_a,_b,_c);};
+ sus_attr_const sus_attr_inline sus_attr_useret sus_inline unsigned short zap_priv_cxxtg_fma(unsigned short const _a,unsigned short const _b,unsigned short const _c) {return ::zap_fma_us( _a,_b,_c);};
+}
+
+#define zap_abs_tg(_val) (::zap_priv_cxxtg_abs( _val))
+#define zap_fma_tg(_a, _b,_c) (::zap_priv_cxxtg_fma(_a, _b,_c))
+
+#endif
+
+#if defined(sus_lang_cxx)
+}
+#endif
+
+#endif
diff --git a/zap/include/zap/mem.h b/zap/include/zap/mem.h
new file mode 100644
index 0000000..20d7326
--- /dev/null
+++ b/zap/include/zap/mem.h
@@ -0,0 +1,59 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/base.h>
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <susinfo.h>
+
+#if !defined(zap_priv_hdr_mem)
+#define zap_priv_hdr_mem
+
+#if defined(sus_lang_asm)
+
+.extern zap_fndbyte
+.extern zap_fndchr
+.extern zap_foreach
+.extern zap_memcmp
+.extern zap_memcpy
+.extern zap_memeq
+.extern zap_memfill
+.extern zap_memfill
+.extern zap_strcmp
+.extern zap_strcpy
+.extern zap_streq
+.extern zap_strfill
+.extern zap_strlen
+
+#else
+
+#if defined(sus_lang_cxx)
+extern "C" {
+#endif
+
+sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_fndbyte( void const * ptr, size_t num, unsigned char byte);
+sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_fndchr( char const * str, char chr);
+sus_attr_hot void zap_foreach( void * ptr, size_t sz, size_t num, void (* fn)(void *));
+sus_attr_hot sus_attr_nothrw sus_attr_useret int_least8_t zap_memcmp( void const * lstr,size_t num, void const * rstr);
+sus_attr_hot sus_attr_nothrw void zap_memcpy( void const * in, size_t num, void * out);
+sus_attr_alloc sus_attr_allocsz(0x2) sus_attr_hot sus_attr_nothrw sus_attr_useret void * zap_memdup( void const * ptr, size_t num);
+sus_attr_hot sus_attr_nothrw sus_attr_useret bool zap_memeq( void const * lptr,size_t num, void const * rptr);
+sus_attr_hot sus_attr_nothrw void zap_memfill( void * ptr, size_t num, unsigned char val);
+sus_attr_hot sus_attr_nothrw sus_attr_useret int_least8_t zap_strcmp( char const * lstr,char const * rstr);
+sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_strcpy( char const * in, char * out);
+sus_attr_alloc sus_attr_hot sus_attr_nothrw sus_attr_useret char * zap_strdup( char const * str);
+sus_attr_hot sus_attr_nothrw sus_attr_useret bool zap_streq( char const * lstr,char const * rstr);
+sus_attr_hot sus_attr_nothrw void zap_strfill( char * lstr,char chr);
+sus_attr_hot sus_attr_nothrw sus_attr_useret size_t zap_strlen( char const * str);
+
+#endif
+#if defined(sus_lang_cxx)
+}
+#endif
+
+#endif
diff --git a/zap/src/abs.c b/zap/src/abs.c
new file mode 100644
index 0000000..8fe97e6
--- /dev/null
+++ b/zap/src/abs.c
@@ -0,0 +1,96 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+#include <zap/math.h>
+
+#include <stdint.h>
+
+#if zap_priv_fastimpl
+__asm__ (
+ ".globl zap_abs_c\n"
+ ".globl zap_abs_i\n"
+ ".globl zap_abs_l\n"
+ ".globl zap_abs_ll\n"
+ ".globl zap_abs_s\n"
+
+ "zap_abs_c:\n"
+ /*
+ signed char val
+ */
+#if defined(sus_arch_amd64) || defined(sus_arch_ia32)
+ "movb %dil,%al\n"
+ "sarb $0x3F,%al\n"
+ "xorb %al,%dil\n"
+ "subb %al,%dil\n"
+ "movb %dil,%al\n"
+ "ret\n"
+#endif
+
+ "zap_abs_i:\n"
+ /*
+ int val
+ */
+#if defined(sus_arch_amd64) || defined(sus_arch_ia32)
+ "movl %edi,%eax\n"
+ "sarl $0x3F,%eax\n"
+ "xorl %eax,%edi\n"
+ "subl %eax,%edi\n"
+ "movl %edi,%eax\n"
+ "ret\n"
+#endif
+
+ "zap_abs_l:\n"
+ /*
+ long val
+ */
+#if defined(sus_arch_amd64)
+ "movq %rdi,%rax\n"
+ "sarq $0x3F,%rax\n"
+ "xorq %rax,%rdi\n"
+ "subq %rax,%rdi\n"
+ "movq %rdi,%rax\n"
+ "ret\n"
+#endif
+
+ "zap_abs_ll:\n"
+ /*
+ long long val
+ */
+#if defined(sus_arch_amd64)
+ "movq %rdi,%rax\n"
+ "sarq $0x3F,%rax\n"
+ "xorq %rax,%rdi\n"
+ "subq %rax,%rdi\n"
+ "movq %rdi,%rax\n"
+ "ret\n"
+#endif
+
+ "zap_abs_s:\n"
+ /*
+ short val
+ */
+#if defined(sus_arch_amd64) || defined(sus_arch_ia32)
+ "movw %di,%ax\n"
+ "sarw $0x3F,%ax\n"
+ "xorw %ax,%di\n"
+ "subw %ax,%di\n"
+ "movw %di,%ax\n"
+ "ret\n"
+#endif
+);
+#else
+#define zap_local_abs(_typ,_sufx) \
+ _typ zap_abs_ ## _sufx (_typ const _val) {return _val > (_typ)0x0 ? _val : -_val;}
+
+zap_local_abs(signed char,c)
+zap_local_abs(int,i)
+zap_local_abs(long,l)
+zap_local_abs(long long,ll)
+zap_local_abs(short,s)
+
+#endif
diff --git a/zap/src/fastimpl.c b/zap/src/fastimpl.c
index 71ded00..2541a41 100644
--- a/zap/src/fastimpl.c
+++ b/zap/src/fastimpl.c
@@ -9,8 +9,4 @@
#include <stdbool.h>
#include <stdint.h>
-#if defined(zap_priv_fastimpl)
-bool const zap_fastimpl = true;
-#else
-bool const zap_fastimpl = false;
-#endif
+bool const zap_fastimpl = zap_priv_fastimpl;
diff --git a/zap/src/fma.c b/zap/src/fma.c
new file mode 100644
index 0000000..b2f45ad
--- /dev/null
+++ b/zap/src/fma.c
@@ -0,0 +1,171 @@
+/*
+ Copyright 2022 Gabriel Jensen.
+ This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+#include <zap/priv.h>
+
+#include <zap/math.h>
+
+#include <stdint.h>
+
+#if zap_priv_fastimpl
+__asm__ (
+ ".globl zap_fma_c\n"
+ ".globl zap_fma_i\n"
+ ".globl zap_fma_l\n"
+ ".globl zap_fma_ll\n"
+ ".globl zap_fma_s\n"
+ ".globl zap_fma_uc\n"
+ ".globl zap_fma_ui\n"
+ ".globl zap_fma_ul\n"
+ ".globl zap_fma_ull\n"
+ ".globl zap_fma_us\n"
+
+ "zap_fma_c:\n"
+ /*
+ signed char a
+ signed char b
+ signed char c
+ */
+#if defined(sus_arch_amd64)
+ "movb %sil,%al\n"
+ "imulb %dl\n"
+ "addb %dil,%al\n"
+ "ret\n"
+#endif
+
+ "zap_fma_i:\n"
+ /*
+ int a
+ int b
+ int c
+ */
+#if defined(sus_arch_amd64)
+ "movl %edx,%eax\n"
+ "imull %esi\n"
+ "addl %edi,%eax\n"
+ "ret\n"
+#endif
+
+ "zap_fma_l:\n"
+ /*
+ long a
+ long b
+ long c
+ */
+#if defined(sus_arch_amd64)
+ "movq %rdx,%rax\n"
+ "imulq %rsi\n"
+ "addq %rdi,%rax\n"
+ "ret\n"
+#endif
+
+ "zap_fma_ll:\n"
+ /*
+ long long a
+ long long b
+ long long c
+ */
+#if defined(sus_arch_amd64)
+ "movq %rdx,%rax\n"
+ "imulq %rsi\n"
+ "addq %rdi,%rax\n"
+ "ret\n"
+#endif
+
+ "zap_fma_s:\n"
+ /*
+ short a
+ short b
+ short c
+ */
+#if defined(sus_arch_amd64)
+ "movw %dx,%ax\n"
+ "imulw %si\n"
+ "addw %di,%ax\n"
+ "ret\n"
+#endif
+
+ "zap_fma_uc:\n"
+ /*
+ unsigned char a
+ unsigned char b
+ unsigned char c
+ */
+#if defined(sus_arch_amd64)
+ "movb %sil,%al\n" /* mulb uses ax instead of al:dl (like the other variants), so we don't need to worry about it overwritting dl. */
+ "mulb %dl\n"
+ "addb %dil,%al\n"
+ "ret\n"
+#endif
+
+ "zap_fma_ui:\n"
+ /*
+ unsigned int a
+ unsigned int b
+ unsigned int c
+ */
+#if defined(sus_arch_amd64)
+ "movl %edx,%eax\n"
+ "mull %esi\n"
+ "addl %edi,%eax\n"
+ "ret\n"
+#endif
+
+ "zap_fma_ul:\n"
+ /*
+ unsigned long a
+ unsigned long b
+ unsigned long c
+ */
+#if defined(sus_arch_amd64)
+ "movq %rdx,%rax\n"
+ "mulq %rsi\n"
+ "addq %rdi,%rax\n"
+ "ret\n"
+#endif
+
+ "zap_fma_ull:\n"
+ /*
+ unsigned long long a
+ unsigned long long b
+ unsigned long long c
+ */
+#if defined(sus_arch_amd64)
+ "movq %rdx,%rax\n" /* rdx get overwritten by mulq, so might as well just make it the first operand (in multiplication, the order is meaningless). */
+ "mulq %rsi\n"
+ "addq %rdi,%rax\n"
+ "ret\n"
+#endif
+
+ "zap_fma_us:\n"
+ /*
+ unsigned short a
+ unsigned short b
+ unsigned short c
+ */
+#if defined(sus_arch_amd64)
+ "movw %dx,%ax\n"
+ "mulw %si\n"
+ "addw %di,%ax\n"
+ "ret\n"
+#endif
+);
+#else
+#define zap_local_fma(_typ,_sufx) \
+ _typ zap_fma_ ## _sufx (_typ const _a,_typ const _b,_typ const _c) {return _a + _b * _c;}
+
+zap_local_fma(signed char,c)
+zap_local_fma(int,i)
+zap_local_fma(long,l)
+zap_local_fma(long long,ll)
+zap_local_fma(short,s)
+zap_local_fma(unsigned char,uc)
+zap_local_fma(unsigned int,ui)
+zap_local_fma(unsigned long,ul)
+zap_local_fma(unsigned long long,ull)
+zap_local_fma(unsigned short,us)
+
+#endif
diff --git a/zap/src/fndbyte.c b/zap/src/fndbyte.c
index 3283eec..e6e6070 100644
--- a/zap/src/fndbyte.c
+++ b/zap/src/fndbyte.c
@@ -6,18 +6,20 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stddef.h>
#include <stdint.h>
-#if defined(zap_priv_fastimpl)
+#if zap_priv_fastimpl
__asm__ (
".globl zap_fndbyte\n"
"zap_fndbyte:\n"
/*
- void const * ptr
- size_t num
- uint_least8_t byte
+ void const * pos
+ size_t num
+ unsigned char byte
*/
#if defined(sus_arch_amd64)
/* rax: Address of the current element. */
@@ -68,10 +70,11 @@ __asm__ (
#endif
);
#else
-size_t zap_fndbyte(void const * const _ptr,size_t const _num,uint_least8_t const _byte) {
- uint_least8_t const * ptr = (uint_least8_t const *)_ptr;
- uint_least8_t const * const afterbuf = ptr + _num;
- for (;ptr != afterbuf;++ptr) {sus_unlikely (*ptr == _byte) {return ptr - (uint_least8_t const *)_ptr;}}
+size_t zap_fndbyte(void const * const _ptr,size_t const _num,unsigned char const _byte) {
+ unsigned char const * startpos = _ptr;
+ unsigned char const * pos = startpos;
+ unsigned char const * const afterbuf = pos + _num;
+ for (;pos != afterbuf;++pos) {sus_unlikely (*pos == _byte) {return pos - startpos;}}
return SIZE_MAX;
}
#endif
diff --git a/zap/src/fndchr.c b/zap/src/fndchr.c
index 5cf78f8..fc4eb2b 100644
--- a/zap/src/fndchr.c
+++ b/zap/src/fndchr.c
@@ -6,10 +6,12 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stddef.h>
#include <stdint.h>
-#if defined(zap_priv_fastimpl)
+#if zap_priv_fastimpl
__asm__ (
".globl zap_fndchr\n"
diff --git a/zap/src/foreach.c b/zap/src/foreach.c
index 54911e9..5e281d4 100644
--- a/zap/src/foreach.c
+++ b/zap/src/foreach.c
@@ -6,11 +6,13 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stddef.h>
void zap_foreach(void * const _ptr,size_t const _sz,size_t const _num,void (* const _fn)(void *)) {
- unsigned char * ptr = _ptr;
- size_t const numbyte = _sz * _num;
- void * const afterbuf = ptr + numbyte;
- for (;ptr != afterbuf;ptr += _sz) {_fn(ptr);}
+ unsigned char * pos = _ptr;
+ size_t const numbyte = _sz * _num;
+ unsigned char * const afterbuf = pos + numbyte;
+ for (;pos != afterbuf;pos += _sz) {_fn(pos);}
}
diff --git a/zap/src/memcmp.c b/zap/src/memcmp.c
index 31e5161..0fdf13a 100644
--- a/zap/src/memcmp.c
+++ b/zap/src/memcmp.c
@@ -6,16 +6,18 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stddef.h>
int_least8_t zap_memcmp(void const * const _lstr,size_t const _num,void const * const _rstr) {
- unsigned char const * lpos = (unsigned char const *)_lstr;
- unsigned char const * rpos = (unsigned char const *)_rstr;
+ unsigned char const * lpos = _lstr;
+ unsigned char const * rpos = _rstr;
unsigned char const * const afterlbuf = lpos + _num;
for (;lpos != afterlbuf;++lpos,++rpos) {
unsigned char const lbyte = *lpos;
unsigned char const rbyte = *rpos;
- sus_likely (lbyte != rbyte) {return lbyte < rbyte ? INT8_MIN : INT8_MAX;}
+ sus_likely (lbyte != rbyte) {return lbyte < rbyte ? INT_LEAST8_MIN : INT_LEAST8_MAX;}
}
return 0x0;
}
diff --git a/zap/src/memcpy.c b/zap/src/memcpy.c
index 8fa98ae..ae923c3 100644
--- a/zap/src/memcpy.c
+++ b/zap/src/memcpy.c
@@ -6,10 +6,12 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stddef.h>
#include <stdint.h>
-#if defined(zap_priv_fastimpl)
+#if zap_priv_fastimpl
__asm__ (
".globl zap_memcpy\n"
@@ -133,9 +135,9 @@ __asm__ (
);
#else
void zap_memcpy(void const * const _in,size_t const _num,void * const _out) {
- uint_least8_t const * in = (uint_least8_t const *)_in;
- uint_least8_t * out = (uint_least8_t *)_out;
- uint_least8_t const * const afterbuf = in + _num;
+ unsigned char const * in = _in;
+ unsigned char * out = _out;
+ unsigned char const * const afterbuf = in + _num;
for (;in != afterbuf;++in,++out) {*out = *in;}
}
#endif
diff --git a/zap/src/memdup.c b/zap/src/memdup.c
index 3670eb3..9b56314 100644
--- a/zap/src/memdup.c
+++ b/zap/src/memdup.c
@@ -6,6 +6,8 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stdlib.h>
void * zap_memdup(sus_attr_unused void const * const _ptr,sus_attr_unused size_t const _num) {
diff --git a/zap/src/memeq.c b/zap/src/memeq.c
index 75ecc12..7dce213 100644
--- a/zap/src/memeq.c
+++ b/zap/src/memeq.c
@@ -6,11 +6,13 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
-#if defined(zap_priv_fastimpl)
+#if zap_priv_fastimpl
__asm__ (
".globl zap_memeq\n"
@@ -101,9 +103,9 @@ __asm__ (
);
#else
bool zap_memeq(void const * const _lptr,size_t const _num,void const * const _rptr) {
- uint_least8_t const * lpos = (uint_least8_t const *)_lptr;
- uint_least8_t const * rpos = (uint_least8_t const *)_rptr;
- uint_least8_t const * const afterbuf = lpos + _num;
+ unsigned char const * lpos = _lptr;
+ unsigned char const * rpos = _rptr;
+ unsigned char const * const afterbuf = lpos + _num;
for (;lpos != afterbuf;++lpos,++rpos) {sus_likely (*lpos != *rpos) {return false;}}
return true;
}
diff --git a/zap/src/memfill.c b/zap/src/memfill.c
index c9a9797..1aebd29 100644
--- a/zap/src/memfill.c
+++ b/zap/src/memfill.c
@@ -6,18 +6,20 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stddef.h>
#include <stdint.h>
-#if defined(zap_priv_fastimpl)
+#if zap_priv_fastimpl
__asm__ (
".globl zap_memfill\n"
"zap_memfill:\n"
/*
- void const * ptr
- size_t num
- uint_least8_t val
+ void const * ptr
+ size_t num
+ unsigned char val
*/
#if defined(sus_arch_amd64)
/* rdi: Address of the current element. */
@@ -50,9 +52,9 @@ __asm__ (
#endif
);
#else
-void zap_memfill(void * const _ptr,size_t const _num,uint_least8_t const _byte) {
- uint_least8_t * pos = (uint_least8_t *)_ptr;
- uint_least8_t * const afterbuf = pos + _num;
+void zap_memfill(void * const _ptr,size_t const _num,unsigned char const _byte) {
+ unsigned char * pos = _ptr;
+ unsigned char * const afterbuf = pos + _num;
for (;pos != afterbuf;++pos) {*pos = _byte;}
}
#endif
diff --git a/zap/src/strcmp.c b/zap/src/strcmp.c
index 101f7dc..0ed0a59 100644
--- a/zap/src/strcmp.c
+++ b/zap/src/strcmp.c
@@ -6,6 +6,8 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stdint.h>
int_least8_t zap_strcmp(char const * const _lstr,char const * const _rstr) {
@@ -14,7 +16,7 @@ int_least8_t zap_strcmp(char const * const _lstr,char const * const _rstr) {
for (;;++lpos,++rpos) {
unsigned char const lchr = *lpos;
unsigned char const rchr = *rpos;
- sus_likely (lchr != rchr) {return lchr < rchr ? INT8_MIN : INT8_MAX;}
+ sus_likely (lchr != rchr) {return lchr < rchr ? INT_LEAST8_MIN : INT_LEAST8_MAX;}
sus_unlikely (lchr == (unsigned char)0x0) {return 0x0;}
}
sus_unreach();
diff --git a/zap/src/strcpy.c b/zap/src/strcpy.c
index 943cb2c..616af7f 100644
--- a/zap/src/strcpy.c
+++ b/zap/src/strcpy.c
@@ -6,9 +6,11 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stddef.h>
-#if defined(zap_priv_fastimpl)
+#if zap_priv_fastimpl
__asm__ (
".globl zap_strcpy\n"
@@ -62,7 +64,7 @@ size_t zap_strcpy(char const * const _in,char * const _out) {
for (;;++inpos,++outpos) {
char const chr = *inpos;
*outpos = chr;
- if (chr == '\x0') {return (size_t)(inpos - _in);}
+ if (chr == '\x0') {return inpos - _in;}
}
sus_unreach();
}
diff --git a/zap/src/strdup.c b/zap/src/strdup.c
index a7ab6e6..183a909 100644
--- a/zap/src/strdup.c
+++ b/zap/src/strdup.c
@@ -6,6 +6,8 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stdlib.h>
char * zap_strdup(sus_attr_unused char const * const _str) {
diff --git a/zap/src/streq.c b/zap/src/streq.c
index 9221cec..1ff4420 100644
--- a/zap/src/streq.c
+++ b/zap/src/streq.c
@@ -6,10 +6,12 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stdbool.h>
#include <stdint.h>
-#if defined(zap_priv_fastimpl)
+#if zap_priv_fastimpl
__asm__ (
".globl zap_streq\n"
diff --git a/zap/src/strfill.c b/zap/src/strfill.c
index a113094..bd0af33 100644
--- a/zap/src/strfill.c
+++ b/zap/src/strfill.c
@@ -6,6 +6,8 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stdint.h>
-void zap_strfill(char * const _str,char const _chr) {zap_memfill(_str,zap_strlen(_str),(uint_least8_t)_chr);}
+void zap_strfill(char * const _str,char const _chr) {zap_memfill(_str,zap_strlen(_str),(unsigned char)_chr);}
diff --git a/zap/src/strlen.c b/zap/src/strlen.c
index eab12e6..84b7d28 100644
--- a/zap/src/strlen.c
+++ b/zap/src/strlen.c
@@ -6,9 +6,11 @@
#include <zap/priv.h>
+#include <zap/mem.h>
+
#include <stddef.h>
-#if defined(zap_priv_fastimpl)
+#if zap_priv_fastimpl
__asm__ (
".globl zap_strlen\n"