Browse Source

Ready. Set. Go!

rexim 4 years ago
commit
b90c0551d8
6 changed files with 557 additions and 0 deletions
  1. 2 0
      .gitignore
  2. 20 0
      LICENSE
  3. 10 0
      Makefile
  4. 11 0
      README.md
  5. 373 0
      la.h
  6. 141 0
      lag.c

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+lag
+la.o

+ 20 - 0
LICENSE

@@ -0,0 +1,20 @@
+Copyright 2021 Alexey Kutepov <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 10 - 0
Makefile

@@ -0,0 +1,10 @@
+CFLAGS=-Wall -Wextra -std=c11 -pedantic
+
+la.o: la.h
+	$(CC) $(CFLAGS) -DLA_IMPLEMENTATION -x c -c la.h
+
+la.h: lag
+	./lag > la.h
+
+lag: lag.c
+	$(CC) $(CFLAGS) -o lag lag.c

+ 11 - 0
README.md

@@ -0,0 +1,11 @@
+# Linear Algebra in C
+
+## Quick Start
+
+Grab [la.h](./la.h) and use it as an stb-style header-only library. For more info on such libraries see: https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
+
+## Regenerating la.h
+
+```console
+$ make
+```

+ 373 - 0
la.h

@@ -0,0 +1,373 @@
+#ifndef LA_H_
+#define LA_H_
+
+#include <stdlib.h>
+
+typedef struct { float c[2]; } V2f;
+typedef struct { double c[2]; } V2d;
+typedef struct { int c[2]; } V2i;
+typedef struct { unsigned int c[2]; } V2u;
+
+typedef struct { float c[3]; } V3f;
+typedef struct { double c[3]; } V3d;
+typedef struct { int c[3]; } V3i;
+typedef struct { unsigned int c[3]; } V3u;
+
+typedef struct { float c[4]; } V4f;
+typedef struct { double c[4]; } V4d;
+typedef struct { int c[4]; } V4i;
+typedef struct { unsigned int c[4]; } V4u;
+
+V2f v2f_sum(V2f a, V2f b);
+V2f v2f_sub(V2f a, V2f b);
+V2f v2f_mul(V2f a, V2f b);
+V2f v2f_div(V2f a, V2f b);
+
+V2d v2d_sum(V2d a, V2d b);
+V2d v2d_sub(V2d a, V2d b);
+V2d v2d_mul(V2d a, V2d b);
+V2d v2d_div(V2d a, V2d b);
+
+V2i v2i_sum(V2i a, V2i b);
+V2i v2i_sub(V2i a, V2i b);
+V2i v2i_mul(V2i a, V2i b);
+V2i v2i_div(V2i a, V2i b);
+
+V2u v2u_sum(V2u a, V2u b);
+V2u v2u_sub(V2u a, V2u b);
+V2u v2u_mul(V2u a, V2u b);
+V2u v2u_div(V2u a, V2u b);
+
+V3f v3f_sum(V3f a, V3f b);
+V3f v3f_sub(V3f a, V3f b);
+V3f v3f_mul(V3f a, V3f b);
+V3f v3f_div(V3f a, V3f b);
+
+V3d v3d_sum(V3d a, V3d b);
+V3d v3d_sub(V3d a, V3d b);
+V3d v3d_mul(V3d a, V3d b);
+V3d v3d_div(V3d a, V3d b);
+
+V3i v3i_sum(V3i a, V3i b);
+V3i v3i_sub(V3i a, V3i b);
+V3i v3i_mul(V3i a, V3i b);
+V3i v3i_div(V3i a, V3i b);
+
+V3u v3u_sum(V3u a, V3u b);
+V3u v3u_sub(V3u a, V3u b);
+V3u v3u_mul(V3u a, V3u b);
+V3u v3u_div(V3u a, V3u b);
+
+V4f v4f_sum(V4f a, V4f b);
+V4f v4f_sub(V4f a, V4f b);
+V4f v4f_mul(V4f a, V4f b);
+V4f v4f_div(V4f a, V4f b);
+
+V4d v4d_sum(V4d a, V4d b);
+V4d v4d_sub(V4d a, V4d b);
+V4d v4d_mul(V4d a, V4d b);
+V4d v4d_div(V4d a, V4d b);
+
+V4i v4i_sum(V4i a, V4i b);
+V4i v4i_sub(V4i a, V4i b);
+V4i v4i_mul(V4i a, V4i b);
+V4i v4i_div(V4i a, V4i b);
+
+V4u v4u_sum(V4u a, V4u b);
+V4u v4u_sub(V4u a, V4u b);
+V4u v4u_mul(V4u a, V4u b);
+V4u v4u_div(V4u a, V4u b);
+
+#endif // LA_H_
+
+#ifdef LA_IMPLEMENTATION
+
+V2f v2f_sum(V2f a, V2f b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V2f v2f_sub(V2f a, V2f b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V2f v2f_mul(V2f a, V2f b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V2f v2f_div(V2f a, V2f b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V2d v2d_sum(V2d a, V2d b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V2d v2d_sub(V2d a, V2d b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V2d v2d_mul(V2d a, V2d b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V2d v2d_div(V2d a, V2d b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V2i v2i_sum(V2i a, V2i b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V2i v2i_sub(V2i a, V2i b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V2i v2i_mul(V2i a, V2i b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V2i v2i_div(V2i a, V2i b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V2u v2u_sum(V2u a, V2u b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V2u v2u_sub(V2u a, V2u b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V2u v2u_mul(V2u a, V2u b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V2u v2u_div(V2u a, V2u b)
+{
+    for (size_t i = 0; i < 2; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V3f v3f_sum(V3f a, V3f b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V3f v3f_sub(V3f a, V3f b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V3f v3f_mul(V3f a, V3f b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V3f v3f_div(V3f a, V3f b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V3d v3d_sum(V3d a, V3d b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V3d v3d_sub(V3d a, V3d b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V3d v3d_mul(V3d a, V3d b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V3d v3d_div(V3d a, V3d b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V3i v3i_sum(V3i a, V3i b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V3i v3i_sub(V3i a, V3i b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V3i v3i_mul(V3i a, V3i b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V3i v3i_div(V3i a, V3i b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V3u v3u_sum(V3u a, V3u b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V3u v3u_sub(V3u a, V3u b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V3u v3u_mul(V3u a, V3u b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V3u v3u_div(V3u a, V3u b)
+{
+    for (size_t i = 0; i < 3; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V4f v4f_sum(V4f a, V4f b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V4f v4f_sub(V4f a, V4f b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V4f v4f_mul(V4f a, V4f b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V4f v4f_div(V4f a, V4f b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V4d v4d_sum(V4d a, V4d b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V4d v4d_sub(V4d a, V4d b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V4d v4d_mul(V4d a, V4d b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V4d v4d_div(V4d a, V4d b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V4i v4i_sum(V4i a, V4i b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V4i v4i_sub(V4i a, V4i b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V4i v4i_mul(V4i a, V4i b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V4i v4i_div(V4i a, V4i b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+V4u v4u_sum(V4u a, V4u b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] += b.c[i];
+    return a;
+}
+
+V4u v4u_sub(V4u a, V4u b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] -= b.c[i];
+    return a;
+}
+
+V4u v4u_mul(V4u a, V4u b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] *= b.c[i];
+    return a;
+}
+
+V4u v4u_div(V4u a, V4u b)
+{
+    for (size_t i = 0; i < 4; ++i) a.c[i] /= b.c[i];
+    return a;
+}
+
+#endif // LA_IMPLEMENTATION

+ 141 - 0
lag.c

@@ -0,0 +1,141 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+typedef struct {
+    const char *name;
+    const char *suffix;
+} Type_Def;
+
+typedef enum {
+    TYPE_DEF_FLOAT = 0,
+    TYPE_DEF_DOUBLE,
+    TYPE_DEF_INT,
+    TYPE_DEF_UNSIGNED_INT,
+    COUNT_TYPE_DEFS,
+} Type_Def_Type;
+
+static Type_Def type_defs[COUNT_TYPE_DEFS] = {
+    [TYPE_DEF_FLOAT]        = {.name = "float", .suffix = "f"},
+    [TYPE_DEF_DOUBLE]       = {.name = "double", .suffix = "d"},
+    [TYPE_DEF_INT]          = {.name = "int", .suffix = "i"},
+    [TYPE_DEF_UNSIGNED_INT] = {.name = "unsigned int", .suffix = "u"},
+};
+
+typedef enum {
+    OP_DEF_SUM = 0,
+    OP_DEF_SUB,
+    OP_DEF_MUL,
+    OP_DEF_DIV,
+    COUNT_OP_DEFS,
+} Op_Def_Type;
+
+typedef struct {
+    const char *suffix;
+    const char *op;
+} Op_Def;
+
+static Op_Def op_defs[COUNT_OP_DEFS] = {
+    [OP_DEF_SUM] = {.suffix = "sum", .op = "+="},
+    [OP_DEF_SUB] = {.suffix = "sub", .op = "-="},
+    [OP_DEF_MUL] = {.suffix = "mul", .op = "*="},
+    [OP_DEF_DIV] = {.suffix = "div", .op = "/="},
+};
+
+typedef struct {
+    char data[128];
+} Short_String;
+
+Short_String shortf(const char *fmt, ...)
+{
+    Short_String result = {0};
+
+    va_list args;
+    va_start(args, fmt);
+    int n = vsnprintf(result.data, sizeof(result.data), fmt, args);
+    assert(n >= 0);
+    assert((size_t) n + 1 <= sizeof(result.data));
+    va_end(args);
+
+    return result;
+}
+
+void gen_vector_def(FILE *stream, size_t n, Type_Def type_def)
+{
+    fprintf(stream, "typedef struct { %s c[%zu]; } V%zu%s;\n",
+            type_def.name, n, n, type_def.suffix);
+}
+
+Short_String vector_op_sig(size_t n, Type_Def type_def, Op_Def op_def)
+{
+    Short_String type = shortf("V%zu%s", n, type_def.suffix);
+    Short_String op_prefix = shortf("v%zu%s", n, type_def.suffix);
+
+    return shortf("%s %s_%s(%s a, %s b)",
+                  type.data,
+                  op_prefix.data, op_def.suffix,
+                  type.data, type.data);
+}
+
+void gen_vector_op_decl(FILE *stream, size_t n, Type_Def type_def, Op_Def op_def)
+{
+    fprintf(stream, "%s;\n", vector_op_sig(n, type_def, op_def).data);
+}
+
+void gen_vector_op_impl(FILE *stream, size_t n, Type_Def type_def, Op_Def op_def)
+{
+    fprintf(stream, "%s\n", vector_op_sig(n, type_def, op_def).data);
+    fprintf(stream, "{\n");
+    fprintf(stream, "    for (size_t i = 0; i < %zu; ++i) a.c[i] %s b.c[i];\n", n, op_def.op);
+    fprintf(stream, "    return a;\n");
+    fprintf(stream, "}\n");
+}
+
+int main()
+{
+    // Header Part
+    {
+        fprintf(stdout, "#ifndef LA_H_\n");
+        fprintf(stdout, "#define LA_H_\n");
+        fprintf(stdout, "\n");
+        fprintf(stdout, "#include <stdlib.h>\n");
+        fprintf(stdout, "\n");
+
+        for (size_t n = 2; n <= 4; ++n) {
+            for (Type_Def_Type i = 0; i < COUNT_TYPE_DEFS; ++i) {
+                gen_vector_def(stdout, n, type_defs[i]);
+            }
+            fprintf(stdout, "\n");
+        }
+
+        for (size_t n = 2; n <= 4; ++n) {
+            for (Type_Def_Type type = 0; type < COUNT_TYPE_DEFS; ++type) {
+                for (Op_Def_Type op = 0; op < COUNT_OP_DEFS; ++op) {
+                    gen_vector_op_decl(stdout, n, type_defs[type], op_defs[op]);
+                }
+                fprintf(stdout, "\n");
+            }
+        }
+
+        fprintf(stdout, "#endif // LA_H_\n");
+        fprintf(stdout, "\n");
+    }
+
+    // C part
+    {
+        fprintf(stdout, "#ifdef LA_IMPLEMENTATION\n");
+        fprintf(stdout, "\n");
+        for (size_t n = 2; n <= 4; ++n) {
+            for (Type_Def_Type type = 0; type < COUNT_TYPE_DEFS; ++type) {
+                for (Op_Def_Type op = 0; op < COUNT_OP_DEFS; ++op) {
+                    gen_vector_op_impl(stdout, n, type_defs[type], op_defs[op]);
+                    fprintf(stdout, "\n");
+                }
+            }
+        }
+        fprintf(stdout, "#endif // LA_IMPLEMENTATION\n");
+    }
+
+    return 0;
+}