Test...
This commit is contained in:
231
xanguage.h
Normal file
231
xanguage.h
Normal file
@@ -0,0 +1,231 @@
|
||||
/// __ ____ _ _ __ __ _ _ _ __ _ __ _ ___
|
||||
/// \ \/ / _` | '_ \ / _` | | | |/ _` |/ _` |/ _ \
|
||||
/// > < (_| | | | | (_| | |_| | (_| | (_| | __/
|
||||
/// /_/\_\__,_|_| |_|\__, |\__,_|\__,_|\__, |\___|
|
||||
/// |___/ |___/
|
||||
///
|
||||
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
||||
///
|
||||
/// xolatile@chud.cyou - xanguage - Syntax definitions of programming languages that I care about (and some that I don't care about).
|
||||
///
|
||||
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
||||
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
||||
///
|
||||
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
||||
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
||||
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
||||
|
||||
/// Description
|
||||
///
|
||||
/// Xanguage, core programming and scripting language definitions created using Xyntax, with few more output definitions that I care about, for
|
||||
/// example Valgrind. There's not much to document about this library, it's used in my projects Xarbon and Xighlight. You can add support for
|
||||
/// your language of choice by adding one enumeration value, creating header file similar to existing ones, including it here and editing
|
||||
/// functions below to match 'language_count'. If you don't like how I highlight one or more of these languages, feel free to add more fields in
|
||||
/// 'language_structure' or edit existing ones inside 'xanguage' folder. This header file may look unfamiliar, especially to my other projects,
|
||||
/// but that's the cost of highlighting multiple languages in very low amount of code.
|
||||
|
||||
/// Enumeration of supported languages, in no particular order.
|
||||
|
||||
typedef enum {
|
||||
language_common, language_ada, language_c, language_cpp,
|
||||
language_d, language_eaxhla, language_flat, language_fortran,
|
||||
language_pascal, language_python, language_go, language_lua,
|
||||
language_bash, language_haskell, language_valgrind, language_holy_c,
|
||||
language_count
|
||||
} language_enumeration;
|
||||
|
||||
/// Structure of single language definition, highlighting-wise, this will be initialized below, check out how it is used.
|
||||
///
|
||||
/// language_structure * language = null;
|
||||
|
||||
typedef struct {
|
||||
natural comment_colour; /// Colours for basic language syntax information.
|
||||
natural processor_colour;
|
||||
natural character_colour;
|
||||
natural string_colour;
|
||||
natural keyword_colour;
|
||||
natural type_colour;
|
||||
natural bracket_colour;
|
||||
natural operator_colour;
|
||||
natural number_colour;
|
||||
natural lowercase_colour;
|
||||
natural uppercase_colour;
|
||||
natural underscore_colour;
|
||||
natural register_colour;
|
||||
natural extension_colour;
|
||||
natural fatal_colour;
|
||||
natural comment_effect; /// Effects for basic language syntax information.
|
||||
natural processor_effect;
|
||||
natural character_effect;
|
||||
natural string_effect;
|
||||
natural keyword_effect;
|
||||
natural type_effect;
|
||||
natural bracket_effect;
|
||||
natural operator_effect;
|
||||
natural number_effect;
|
||||
natural lowercase_effect;
|
||||
natural uppercase_effect;
|
||||
natural underscore_effect;
|
||||
natural register_effect;
|
||||
natural extension_effect;
|
||||
natural fatal_effect;
|
||||
} language_structure;
|
||||
|
||||
/// Warning: Local macros! You don't need to use this at all, it's covered by other functions, don't worry about it.
|
||||
///
|
||||
/// You shouldn't care about these local macros, they made few lines of code shorter, we're including files in this order, in this place.
|
||||
|
||||
#define language_lowercase "abcdefghijklmnopqrstuvwxyz"
|
||||
#define language_uppercase "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
#define language_letters "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
#define language_digits "0123456789"
|
||||
|
||||
#include <xolatile/xanguage/common.h>
|
||||
#include <xolatile/xanguage/ada.h>
|
||||
#include <xolatile/xanguage/c.h>
|
||||
#include <xolatile/xanguage/c++.h>
|
||||
#include <xolatile/xanguage/d.h>
|
||||
#include <xolatile/xanguage/eaxhla.h>
|
||||
#include <xolatile/xanguage/flat.h>
|
||||
#include <xolatile/xanguage/fortran.h>
|
||||
#include <xolatile/xanguage/pascal.h>
|
||||
#include <xolatile/xanguage/python.h>
|
||||
#include <xolatile/xanguage/go.h>
|
||||
#include <xolatile/xanguage/holy_c.h>
|
||||
#include <xolatile/xanguage/lua.h>
|
||||
#include <xolatile/xanguage/bash.h>
|
||||
#include <xolatile/xanguage/haskell.h>
|
||||
#include <xolatile/xanguage/valgrind.h>
|
||||
|
||||
#undef language_lowercase
|
||||
#undef language_uppercase
|
||||
#undef language_letters
|
||||
#undef language_digits
|
||||
|
||||
/// Array of function pointers enumerated above, these functions are defined in separate header files in 'xanguage' folder.
|
||||
|
||||
static procedure (* language_highlighter [language_count]) (language_structure * language, syntax_structure * syntax) = {
|
||||
language_highlight_common, language_highlight_ada, language_highlight_c, language_highlight_cpp,
|
||||
language_highlight_d, language_highlight_eaxhla, language_highlight_flat, language_highlight_fortran,
|
||||
language_highlight_pascal, language_highlight_python, language_highlight_go, language_highlight_lua,
|
||||
language_highlight_bash, language_highlight_haskell, language_highlight_valgrind, language_highlight_holy_c
|
||||
};
|
||||
|
||||
/// Array of short command line argument enumerated above, makes main function less bloated.
|
||||
|
||||
static character * language_short_option [language_count] = {
|
||||
"-X", "-A", "-C", "-S", "-D", "-E", "-T", "-F", "-P", "-Y", "-G", "-L", "-B", "-H", "-V", "-O"
|
||||
};
|
||||
|
||||
/// Array of long command line argument enumerated above, makes main function less bloated.
|
||||
|
||||
static character * language_long_option [language_count] = {
|
||||
"--common", "--ada", "--c", "--cpp", "--d", "--eaxhla", "--flat", "--fortran",
|
||||
"--pascal", "--python", "--go", "--lua", "--bash", "--haskell", "--valgrind", "--holyc"
|
||||
};
|
||||
|
||||
/// Array of pretty language name enumerated above, makes things pretty.
|
||||
|
||||
static character * language_identifier [language_count] = {
|
||||
"Common", "Ada", "C", "C++", "D", "EAXHLA", "Flat", "Fortran",
|
||||
"Pascal", "Python", "Go", "Lua", "Bash", "Haskell", "Valgrind", "Holy C"
|
||||
};
|
||||
|
||||
/// After you've defined global or local language variable, you want to initialize it, edit this function if you dislike my themes.
|
||||
///
|
||||
/// language = language_initialize (false); /// You're probably using this library to render an image.
|
||||
/// language = language_initialize (true); /// You're probably using this library to print to terminal.
|
||||
|
||||
static language_structure * language_initialize (boolean true_colour) {
|
||||
language_structure * language = allocate (sizeof (* language));
|
||||
|
||||
if (true_colour == true) {
|
||||
language->comment_colour = 0xff777777u;
|
||||
language->processor_colour = 0xff3377aau;
|
||||
language->character_colour = 0xff7733ccu;
|
||||
language->string_colour = 0xffcc3377u;
|
||||
language->keyword_colour = 0xff33cceeu;
|
||||
language->type_colour = 0xff55cceeu;
|
||||
language->bracket_colour = 0xffee5533u;
|
||||
language->operator_colour = 0xffeeaa33u;
|
||||
language->number_colour = 0xffee33aau;
|
||||
language->lowercase_colour = 0xffccccccu;
|
||||
language->uppercase_colour = 0xffeeeeeeu;
|
||||
language->underscore_colour = 0xffaaaaaau;
|
||||
language->register_colour = 0xff5577aau;
|
||||
language->extension_colour = 0xff55aaccu;
|
||||
language->fatal_colour = 0xffcc7755u;
|
||||
} else {
|
||||
language->comment_colour = colour_grey;
|
||||
language->processor_colour = colour_cyan;
|
||||
language->character_colour = colour_pink;
|
||||
language->string_colour = colour_pink;
|
||||
language->keyword_colour = colour_yellow;
|
||||
language->type_colour = colour_yellow;
|
||||
language->bracket_colour = colour_blue;
|
||||
language->operator_colour = colour_cyan;
|
||||
language->number_colour = colour_pink;
|
||||
language->lowercase_colour = colour_white;
|
||||
language->uppercase_colour = colour_white;
|
||||
language->underscore_colour = colour_white;
|
||||
language->register_colour = colour_cyan;
|
||||
language->extension_colour = colour_yellow;
|
||||
language->fatal_colour = colour_red;
|
||||
language->comment_effect = effect_bold;
|
||||
language->processor_effect = effect_italic;
|
||||
language->character_effect = effect_bold;
|
||||
language->string_effect = effect_normal;
|
||||
language->keyword_effect = effect_bold;
|
||||
language->type_effect = effect_normal;
|
||||
language->bracket_effect = effect_bold;
|
||||
language->operator_effect = effect_normal;
|
||||
language->number_effect = effect_bold;
|
||||
language->lowercase_effect = effect_normal;
|
||||
language->uppercase_effect = effect_bold;
|
||||
language->underscore_effect = effect_italic;
|
||||
language->register_effect = effect_italic;
|
||||
language->extension_effect = effect_italic;
|
||||
language->fatal_effect = effect_bold;
|
||||
}
|
||||
|
||||
return (language);
|
||||
}
|
||||
|
||||
/// When you're done doing your thing, just call this function nicely to avoid leaking memory.
|
||||
///
|
||||
/// language = language_deinitialize (language);
|
||||
|
||||
static language_structure * language_deinitialize (language_structure * language) {
|
||||
return (deallocate (language));
|
||||
}
|
||||
|
||||
/// This is just a helper function that I used a lot, it made sense to define it in this file, so here it is... This function will call specific
|
||||
/// function from 'xanguage' folder, based on what file type you pass to it, enumerated in Xtandard. It takes natural number as selection value
|
||||
/// due to avoiding type-related errors that dumb compilers might warn about, because some C compilers treat enumeration values as signed, while
|
||||
/// others treat them as unsigned, unless you manually define some value there negative, which is braindead.
|
||||
///
|
||||
/// language_conditionally_select (language, syntax, selection_index);
|
||||
|
||||
static procedure language_conditionally_select (language_structure * language, syntax_structure * syntax, natural select) {
|
||||
if (syntax->count == 0) {
|
||||
if ((select == file_type_c_source) || (select == file_type_c_header)) {
|
||||
language_highlight_c (language, syntax);
|
||||
} else if ((select == file_type_ada_sexy_body) || (select == file_type_ada_specification)) {
|
||||
language_highlight_ada (language, syntax);
|
||||
} else if ((select == file_type_cpp_source) || (select == file_type_cpp_header)) {
|
||||
language_highlight_cpp (language, syntax);
|
||||
} else if (select == file_type_flat_assembly) {
|
||||
language_highlight_flat (language, syntax);
|
||||
} else if (select == file_type_fortran_90_source) {
|
||||
language_highlight_fortran (language, syntax);
|
||||
} else if (select == file_type_pascal_source) {
|
||||
language_highlight_pascal (language, syntax);
|
||||
} else if (select == file_type_eax_assembly) {
|
||||
language_highlight_eaxhla (language, syntax);
|
||||
} else if (select == file_type_python_script) {
|
||||
language_highlight_python (language, syntax);
|
||||
} else {
|
||||
language_highlight_common (language, syntax);
|
||||
}
|
||||
}
|
||||
}
|
||||
495
xatrix.h
Normal file
495
xatrix.h
Normal file
@@ -0,0 +1,495 @@
|
||||
/// _ _
|
||||
/// __ ____ _| |_ _ __(_)_ __
|
||||
/// \ \/ / _` | __| '__| \ \/ /
|
||||
/// > < (_| | |_| | | |> <
|
||||
/// /_/\_\__,_|\__|_| |_/_/\_\
|
||||
///
|
||||
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
||||
///
|
||||
/// xolatile@chud.cyou - xatrix - Very dumb and slow matrix library, mathematical matrix, because I don't like other people ideas...
|
||||
///
|
||||
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
||||
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
||||
///
|
||||
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
||||
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
||||
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
||||
|
||||
/// Description
|
||||
///
|
||||
/// Xatrix, my tiny braindead unoptimized matrix library. Unlike vectors that use x, y, z and w structure fields, matrices are double array of
|
||||
/// 32-bit floating point numbers, and they're accessed with integers, which should've been the same case with vectors, but mathematicians are
|
||||
/// dumb sometimes (blame it on the one being older than the other one?). Again, nothing much to talk about here, learn linear algebra, include
|
||||
/// this header file in your project, use it however you want, compilers might optimize this better than my vector library. This library isn't
|
||||
/// intended for neural networks, as it's not generic, it can be used in simple CPU-based ray tracers and physics simulations.
|
||||
|
||||
/// Nice 2D, 3D and 4D matrix structures.
|
||||
|
||||
typedef real matrix_2 [2] [2]; /// Tiny 2x2 matrix.
|
||||
typedef real matrix_3 [3] [3]; /// Tiny 3x3 matrix.
|
||||
typedef real matrix_4 [4] [4]; /// Tiny 4x4 matrix.
|
||||
|
||||
/// Assign values to 2D, 3D or 4D matrix and return address of that matrix.
|
||||
|
||||
static matrix_2 * matrix_2_assign (matrix_2 * destination,
|
||||
real m00, real m01,
|
||||
real m10, real m11) {
|
||||
destination [0] [0] = m00; destination [0] [1] = m01;
|
||||
destination [1] [0] = m10; destination [1] [1] = m11;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_assign (matrix_3 * destination,
|
||||
real m00, real m01, real m02,
|
||||
real m10, real m11, real m12,
|
||||
real m20, real m21, real m22) {
|
||||
destination [0] [0] = m00; destination [0] [1] = m01; destination [0] [2] = m02;
|
||||
destination [1] [0] = m10; destination [1] [1] = m11; destination [1] [2] = m12;
|
||||
destination [2] [0] = m20; destination [2] [1] = m21; destination [2] [2] = m22;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_assign (matrix_4 * destination,
|
||||
real m00, real m01, real m02, real m03,
|
||||
real m10, real m11, real m12, real m13,
|
||||
real m20, real m21, real m22, real m23,
|
||||
real m30, real m31, real m32, real m33) {
|
||||
destination [0] [0] = m00; destination [0] [1] = m01; destination [0] [2] = m02; destination [0] [3] = m03;
|
||||
destination [1] [0] = m10; destination [1] [1] = m11; destination [1] [2] = m12; destination [1] [3] = m13;
|
||||
destination [2] [0] = m20; destination [2] [1] = m21; destination [2] [2] = m22; destination [2] [3] = m23;
|
||||
destination [3] [0] = m30; destination [3] [1] = m31; destination [3] [2] = m32; destination [3] [3] = m33;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Nullify values of 2D, 3D or 4D matrix and return address of that matrix.
|
||||
|
||||
static matrix_2 * matrix_2_nullify (matrix_2 * destination) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
destination [row] [column] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_nullify (matrix_3 * destination) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
destination [row] [column] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_nullify (matrix_4 * destination) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
destination [row] [column] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Identify values of 2D, 3D or 4D matrix and return address of that matrix.
|
||||
|
||||
static matrix_2 * matrix_2_identity (matrix_2 * destination) {
|
||||
destination = matrix_2_nullify (destination);
|
||||
|
||||
for (natural index = 0; index < 2; ++index) {
|
||||
destination [index] [index] = 1.0f;
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_identity (matrix_3 * destination) {
|
||||
destination = matrix_3_nullify (destination);
|
||||
|
||||
for (natural index = 0; index < 3; ++index) {
|
||||
destination [index] [index] = 1.0f;
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_identity (matrix_4 * destination) {
|
||||
destination = matrix_4_nullify (destination);
|
||||
|
||||
for (natural index = 0; index < 4; ++index) {
|
||||
destination [index] [index] = 1.0f;
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Return determinant of 2D, 3D or 4D matrix.
|
||||
|
||||
static real matrix_2_determinant (matrix_2 * matrix) {
|
||||
real a = matrix [0] [0] * matrix [1] [1];
|
||||
real b = matrix [0] [1] * matrix [1] [0];
|
||||
|
||||
return (a - b);
|
||||
}
|
||||
|
||||
static real matrix_3_determinant (matrix_3 * matrix) {
|
||||
matrix_2 matrix_a = { { matrix [1] [1], matrix [1] [2] },
|
||||
{ matrix [2] [1], matrix [2] [2] } };
|
||||
matrix_2 matrix_b = { { matrix [1] [0], matrix [1] [2] },
|
||||
{ matrix [2] [0], matrix [2] [2] } };
|
||||
matrix_2 matrix_c = { { matrix [1] [0], matrix [1] [1] },
|
||||
{ matrix [2] [0], matrix [2] [1] } };
|
||||
|
||||
real a = matrix [0] [0] * matrix_2_determinant (& matrix_a);
|
||||
real b = matrix [0] [1] * matrix_2_determinant (& matrix_b);
|
||||
real c = matrix [0] [2] * matrix_2_determinant (& matrix_c);
|
||||
|
||||
return (a - b + c);
|
||||
}
|
||||
|
||||
static real matrix_4_determinant (matrix_4 * matrix) {
|
||||
matrix_3 matrix_a = { { matrix [1] [1], matrix [1] [2], matrix [1] [3] },
|
||||
{ matrix [2] [1], matrix [2] [2], matrix [2] [3] },
|
||||
{ matrix [3] [1], matrix [3] [2], matrix [3] [3] } };
|
||||
matrix_3 matrix_b = { { matrix [1] [0], matrix [1] [2], matrix [1] [3] },
|
||||
{ matrix [2] [0], matrix [2] [2], matrix [2] [3] },
|
||||
{ matrix [3] [0], matrix [3] [2], matrix [3] [3] } };
|
||||
matrix_3 matrix_c = { { matrix [1] [0], matrix [1] [1], matrix [1] [3] },
|
||||
{ matrix [2] [0], matrix [2] [1], matrix [2] [3] },
|
||||
{ matrix [3] [0], matrix [3] [1], matrix [3] [3] } };
|
||||
matrix_3 matrix_d = { { matrix [1] [0], matrix [1] [1], matrix [1] [2] },
|
||||
{ matrix [2] [0], matrix [2] [1], matrix [2] [2] },
|
||||
{ matrix [3] [0], matrix [3] [1], matrix [3] [2] } };
|
||||
|
||||
real a = matrix [0] [0] * matrix_3_determinant (& matrix_a);
|
||||
real b = matrix [0] [1] * matrix_3_determinant (& matrix_b);
|
||||
real c = matrix [0] [2] * matrix_3_determinant (& matrix_c);
|
||||
real d = matrix [0] [3] * matrix_3_determinant (& matrix_d);
|
||||
|
||||
return (a - b + c - d);
|
||||
}
|
||||
|
||||
/// Copy 2D, 3D or 4D source matrix into destination matrix.
|
||||
|
||||
static matrix_2 * matrix_2_copy (matrix_2 * destination, matrix_2 * source) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
destination [row] [column] = source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_copy (matrix_3 * destination, matrix_3 * source) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
destination [row] [column] = source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_copy (matrix_4 * destination, matrix_4 * source) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
destination [row] [column] = source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Scale 2D, 3D or 4D matrix by scalar value and return address of that matrix.
|
||||
|
||||
static matrix_2 * matrix_2_scale (matrix_2 * destination, real scale) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
destination [row] [column] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_scale (matrix_3 * destination, real scale) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
destination [row] [column] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_scale (matrix_4 * destination, real scale) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
destination [row] [column] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Scale 2D, 3D or 4D source matrix by scalar value into destination matrix and return its address.
|
||||
|
||||
static matrix_2 * matrix_2_scale_to (matrix_2 * destination, matrix_2 * source, real scale) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
destination [row] [column] = source [row] [column] * scale;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_scale_to (matrix_3 * destination, matrix_3 * source, real scale) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
destination [row] [column] = source [row] [column] * scale;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_scale_to (matrix_4 * destination, matrix_4 * source, real scale) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
destination [row] [column] = source [row] [column] * scale;
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Add 2D, 3D or 4D source matrix onto destination matrix and return address of destination matrix.
|
||||
|
||||
static matrix_2 * matrix_2_add (matrix_2 * destination, matrix_2 * source) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
destination [row] [column] += source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_add (matrix_3 * destination, matrix_3 * source) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
destination [row] [column] += source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_add (matrix_4 * destination, matrix_4 * source) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
destination [row] [column] += source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Add two 2D, 3D or 4D matrices into destination matrix and return address of destination matrix.
|
||||
|
||||
static matrix_2 * matrix_2_add_to (matrix_2 * destination, matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_add_to (matrix_3 * destination, matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_add_to (matrix_4 * destination, matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
destination [row] [column] = matrix_a [row] [column] + matrix_b [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Subtract 2D, 3D or 4D source matrix from destination matrix and return address of destination matrix.
|
||||
|
||||
static matrix_2 * matrix_2_subtract (matrix_2 * destination, matrix_2 * source) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
destination [row] [column] -= source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_subtract (matrix_3 * destination, matrix_3 * source) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
destination [row] [column] -= source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_subtract (matrix_4 * destination, matrix_4 * source) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
destination [row] [column] -= source [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Subtract two 2D, 3D or 4D matrices, save values into destination matrix and return address of destination matrix.
|
||||
|
||||
static matrix_2 * matrix_2_subtract_to (matrix_2 * destination, matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_subtract_to (matrix_3 * destination, matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_subtract_to (matrix_4 * destination, matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
destination [row] [column] = matrix_a [row] [column] - matrix_b [row] [column];
|
||||
}
|
||||
}
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Multiply two 2D, 3D or 4D matrices, save values into destination matrix and return address of destination matrix.
|
||||
|
||||
static matrix_2 * matrix_2_multiply (matrix_2 * result, matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
result [row] [column] = 0.0f;
|
||||
|
||||
for (natural index = 0; index < 2; ++index) {
|
||||
result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static matrix_3 * matrix_3_multiply (matrix_3 * result, matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
result [row] [column] = 0.0f;
|
||||
|
||||
for (natural index = 0; index < 3; ++index) {
|
||||
result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static matrix_4 * matrix_4_multiply (matrix_4 * result, matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
result [row] [column] = 0.0f;
|
||||
|
||||
for (natural index = 0; index < 4; ++index) {
|
||||
result [row] [column] += matrix_a [row] [index] * matrix_b [index] [column];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/// Return trace of 2D, 3D or 4D matrix.
|
||||
|
||||
static real matrix_2_trace (matrix_2 * matrix) {
|
||||
return (matrix [0] [0] + matrix [1] [1]);
|
||||
}
|
||||
|
||||
static real matrix_3_trace (matrix_3 * matrix) {
|
||||
return (matrix [0] [0] + matrix [1] [1] + matrix [2] [2]);
|
||||
}
|
||||
|
||||
static real matrix_4_trace (matrix_4 * matrix) {
|
||||
return (matrix [0] [0] + matrix [1] [1] + matrix [2] [2] + matrix [3] [3]);
|
||||
}
|
||||
|
||||
/// Compare if two 2D, 3D or 4D matrices are identical and return boolean value of it.
|
||||
|
||||
static boolean matrix_2_compare (matrix_2 * matrix_a, matrix_2 * matrix_b) {
|
||||
for (natural row = 0; row < 2; ++row) {
|
||||
for (natural column = 0; column < 2; ++column) {
|
||||
if (matrix_a [row] [column] != matrix_b [row] [column]) {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static boolean matrix_3_compare (matrix_3 * matrix_a, matrix_3 * matrix_b) {
|
||||
for (natural row = 0; row < 3; ++row) {
|
||||
for (natural column = 0; column < 3; ++column) {
|
||||
if (matrix_a [row] [column] != matrix_b [row] [column]) {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static boolean matrix_4_compare (matrix_4 * matrix_a, matrix_4 * matrix_b) {
|
||||
for (natural row = 0; row < 4; ++row) {
|
||||
for (natural column = 0; column < 4; ++column) {
|
||||
if (matrix_a [row] [column] != matrix_b [row] [column]) {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
438
xector.h
Normal file
438
xector.h
Normal file
@@ -0,0 +1,438 @@
|
||||
/// _
|
||||
/// __ _____ ___| |_ ___ _ __
|
||||
/// \ \/ / _ \/ __| __/ _ \| '__|
|
||||
/// > < __/ (__| || (_) | |
|
||||
/// /_/\_\___|\___|\__\___/|_|
|
||||
///
|
||||
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
||||
///
|
||||
/// xolatile@chud.cyou - xector - Very slow and dumb vector library, mathematical vector, not that C++ cancer by the way...
|
||||
///
|
||||
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
||||
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
||||
///
|
||||
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
||||
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
||||
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
||||
|
||||
/// Description
|
||||
///
|
||||
/// Xector (Vector), my small vector library, not to be confused with my older project Xector (Sector) which was for procedurally generating 3D
|
||||
/// models (based on boolean operations on 3D sectors). This library isn't optimized for performance or memory usage, instead it's for my own
|
||||
/// preferred programming style. It's hard to explain linear algebra to people who don't already know it (for me at least), so I won't do that,
|
||||
/// function names should provide you enough information. There'll be simple comments for the sake of consistency with my other libraries.
|
||||
///
|
||||
/// If you want to use "good" linear algebra library, prefer CGLM over this, and GLM if you're into C++ rather than objectively better language
|
||||
/// called C. Again, reading comments in this file is useless. Include it, set the vectors, do the work.
|
||||
|
||||
/// 2D vector structure.
|
||||
|
||||
typedef struct {
|
||||
real x, y; /// Two 32-bit floating point numbers.
|
||||
} vector_2;
|
||||
|
||||
/// 3D vector structure.
|
||||
|
||||
typedef struct {
|
||||
real x, y, z; /// Three 32-bit floating point numbers.
|
||||
} vector_3;
|
||||
|
||||
/// 4D vector structure.
|
||||
|
||||
typedef struct {
|
||||
real x, y, z, w; /// Why the hell did they choose to start from 'x', and end with 'z', it's so retarded.
|
||||
} vector_4;
|
||||
|
||||
/// Assign values to 2D, 3D or 4D vector and return address of that vector.
|
||||
|
||||
static vector_2 * vector_2_assign (vector_2 * destination, real x, real y) {
|
||||
destination->x = x;
|
||||
destination->y = y;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_assign (vector_3 * destination, real x, real y, real z) {
|
||||
destination->x = x;
|
||||
destination->y = y;
|
||||
destination->z = z;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_assign (vector_4 * destination, real x, real y, real z, real w) {
|
||||
destination->x = x;
|
||||
destination->y = y;
|
||||
destination->z = z;
|
||||
destination->w = w;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Nullify values of 2D, 3D or 4D vector and return address of that vector.
|
||||
|
||||
static vector_2 * vector_2_nullify (vector_2 * destination) {
|
||||
destination->x = destination->y = 0.0f;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_nullify (vector_3 * destination) {
|
||||
destination->x = destination->y = destination->z = 0.0f;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_nullify (vector_4 * destination) {
|
||||
destination->x = destination->y = destination->z = destination->w = 0.0f;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Return length of 2D, 3D or 4D vector.
|
||||
|
||||
static real vector_2_length (vector_2 * vector) {
|
||||
real x = vector->x;
|
||||
real y = vector->y;
|
||||
|
||||
return (square_root (x * x + y * y));
|
||||
}
|
||||
|
||||
static real vector_3_length (vector_3 * vector) {
|
||||
real x = vector->x;
|
||||
real y = vector->y;
|
||||
real z = vector->z;
|
||||
|
||||
return (square_root (x * x + y * y + z * z));
|
||||
}
|
||||
|
||||
static real vector_4_length (vector_4 * vector) {
|
||||
real x = vector->x;
|
||||
real y = vector->y;
|
||||
real z = vector->z;
|
||||
real w = vector->w;
|
||||
|
||||
return (square_root (x * x + y * y + z * z + w * w));
|
||||
}
|
||||
|
||||
/// Normalize 2D, 3D or 4D vector and return address of that vector.
|
||||
|
||||
static vector_2 * vector_2_normalize (vector_2 * destination) {
|
||||
real length = vector_2_length (destination);
|
||||
|
||||
destination->x /= length;
|
||||
destination->y /= length;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_normalize (vector_3 * destination) {
|
||||
real length = vector_3_length (destination);
|
||||
|
||||
destination->x /= length;
|
||||
destination->y /= length;
|
||||
destination->z /= length;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_normalize (vector_4 * destination) {
|
||||
real length = vector_4_length (destination);
|
||||
|
||||
destination->x /= length;
|
||||
destination->y /= length;
|
||||
destination->z /= length;
|
||||
destination->w /= length;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Normalize 2D, 3D or 4D source vector into destination vector and return its address.
|
||||
|
||||
static vector_2 * vector_2_normalize_to (vector_2 * destination, vector_2 * source) {
|
||||
real length = vector_2_length (source);
|
||||
|
||||
destination->x = source->x / length;
|
||||
destination->y = source->y / length;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_normalize_to (vector_3 * destination, vector_3 * source) {
|
||||
real length = vector_3_length (source);
|
||||
|
||||
destination->x = source->x / length;
|
||||
destination->y = source->y / length;
|
||||
destination->z = source->z / length;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_normalize_to (vector_4 * destination, vector_4 * source) {
|
||||
real length = vector_4_length (source);
|
||||
|
||||
destination->x = source->x / length;
|
||||
destination->y = source->y / length;
|
||||
destination->z = source->z / length;
|
||||
destination->w = source->w / length;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Copy 2D, 3D or 4D source vector into destination vector.
|
||||
|
||||
static vector_2 * vector_2_copy (vector_2 * destination, vector_2 * source) {
|
||||
destination->x = source->x;
|
||||
destination->y = source->y;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_copy (vector_3 * destination, vector_3 * source) {
|
||||
destination->x = source->x;
|
||||
destination->y = source->y;
|
||||
destination->z = source->z;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_copy (vector_4 * destination, vector_4 * source) {
|
||||
destination->x = source->x;
|
||||
destination->y = source->y;
|
||||
destination->z = source->z;
|
||||
destination->w = source->w;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Exchange values of two 2D, 3D or 4D vectors.
|
||||
|
||||
static procedure vector_2_exchange (vector_2 * vector_a, vector_2 * vector_b) {
|
||||
exchange_real (& vector_a->x, & vector_b->x);
|
||||
exchange_real (& vector_a->y, & vector_b->y);
|
||||
}
|
||||
|
||||
static procedure vector_3_exchange (vector_3 * vector_a, vector_3 * vector_b) {
|
||||
exchange_real (& vector_a->x, & vector_b->x);
|
||||
exchange_real (& vector_a->y, & vector_b->y);
|
||||
exchange_real (& vector_a->z, & vector_b->z);
|
||||
}
|
||||
|
||||
static procedure vector_4_exchange (vector_4 * vector_a, vector_4 * vector_b) {
|
||||
exchange_real (& vector_a->x, & vector_b->x);
|
||||
exchange_real (& vector_a->y, & vector_b->y);
|
||||
exchange_real (& vector_a->z, & vector_b->z);
|
||||
exchange_real (& vector_a->w, & vector_b->w);
|
||||
}
|
||||
|
||||
/// Scale 2D, 3D or 4D vector by scalar value and return address of that vector.
|
||||
|
||||
static vector_2 * vector_2_scale (vector_2 * destination, real scale) {
|
||||
destination->x *= scale;
|
||||
destination->y *= scale;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_scale (vector_3 * destination, real scale) {
|
||||
destination->x *= scale;
|
||||
destination->y *= scale;
|
||||
destination->z *= scale;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_scale (vector_4 * destination, real scale) {
|
||||
destination->x *= scale;
|
||||
destination->y *= scale;
|
||||
destination->z *= scale;
|
||||
destination->w *= scale;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Scale 2D, 3D or 4D source vector by scalar value into destination vector and return its address.
|
||||
|
||||
static vector_2 * vector_2_scale_to (vector_2 * destination, vector_2 * source, real scale) {
|
||||
destination->x = source->x * scale;
|
||||
destination->y = source->y * scale;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_scale_to (vector_3 * destination, vector_3 * source, real scale) {
|
||||
destination->x = source->x * scale;
|
||||
destination->y = source->y * scale;
|
||||
destination->z = source->z * scale;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_scale_to (vector_4 * destination, vector_4 * source, real scale) {
|
||||
destination->x = source->x * scale;
|
||||
destination->y = source->y * scale;
|
||||
destination->z = source->z * scale;
|
||||
destination->w = source->w * scale;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Add 2D, 3D or 4D source vector onto destination vector and return address of destination vector.
|
||||
|
||||
static vector_2 * vector_2_add (vector_2 * destination, vector_2 * source) {
|
||||
destination->x += source->x;
|
||||
destination->y += source->y;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_add (vector_3 * destination, vector_3 * source) {
|
||||
destination->x += source->x;
|
||||
destination->y += source->y;
|
||||
destination->z += source->z;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_add (vector_4 * destination, vector_4 * source) {
|
||||
destination->x += source->x;
|
||||
destination->y += source->y;
|
||||
destination->z += source->z;
|
||||
destination->w += source->w;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Add two 2D, 3D or 4D vectors into destination vector and return address of destination vector.
|
||||
|
||||
static vector_2 * vector_2_add_to (vector_2 * destination, vector_2 * vector_a, vector_2 * vector_b) {
|
||||
destination->x = vector_a->x + vector_b->x;
|
||||
destination->y = vector_a->y + vector_b->y;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_add_to (vector_3 * destination, vector_3 * vector_a, vector_3 * vector_b) {
|
||||
destination->x = vector_a->x + vector_b->x;
|
||||
destination->y = vector_a->y + vector_b->y;
|
||||
destination->z = vector_a->z + vector_b->z;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_add_to (vector_4 * destination, vector_4 * vector_a, vector_4 * vector_b) {
|
||||
destination->x = vector_a->x + vector_b->x;
|
||||
destination->y = vector_a->y + vector_b->y;
|
||||
destination->z = vector_a->z + vector_b->z;
|
||||
destination->w = vector_a->w + vector_b->w;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Subtract 2D, 3D or 4D source vector from destination vector and return address of destination vector.
|
||||
|
||||
static vector_2 * vector_2_subtract (vector_2 * destination, vector_2 * source) {
|
||||
destination->x -= source->x;
|
||||
destination->y -= source->y;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_subtract (vector_3 * destination, vector_3 * source) {
|
||||
destination->x -= source->x;
|
||||
destination->y -= source->y;
|
||||
destination->z -= source->z;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_subtract (vector_4 * destination, vector_4 * source) {
|
||||
destination->x -= source->x;
|
||||
destination->y -= source->y;
|
||||
destination->z -= source->z;
|
||||
destination->w -= source->w;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Subtract two 2D, 3D or 4D vectors, save values into destination vector and return address of destination vector.
|
||||
|
||||
static vector_2 * vector_2_subtract_to (vector_2 * destination, vector_2 * vector_a, vector_2 * vector_b) {
|
||||
destination->x = vector_a->x - vector_b->x;
|
||||
destination->y = vector_a->y - vector_b->y;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_3 * vector_3_subtract_to (vector_3 * destination, vector_3 * vector_a, vector_3 * vector_b) {
|
||||
destination->x = vector_a->x - vector_b->x;
|
||||
destination->y = vector_a->y - vector_b->y;
|
||||
destination->z = vector_a->z - vector_b->z;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
static vector_4 * vector_4_subtract_to (vector_4 * destination, vector_4 * vector_a, vector_4 * vector_b) {
|
||||
destination->x = vector_a->x - vector_b->x;
|
||||
destination->y = vector_a->y - vector_b->y;
|
||||
destination->z = vector_a->z - vector_b->z;
|
||||
destination->w = vector_a->w - vector_b->w;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
|
||||
/// Compare if two 2D, 3D or 4D vectors are identical and return boolean value of it.
|
||||
|
||||
static boolean vector_2_compare (vector_2 * vector_a, vector_2 * vector_b) {
|
||||
if ((vector_a->x == vector_b->x) && (vector_a->y == vector_b->y)) {
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean vector_3_compare (vector_3 * vector_a, vector_3 * vector_b) {
|
||||
if ((vector_a->x == vector_b->x) && (vector_a->y == vector_b->y) && (vector_a->z == vector_b->z)) {
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean vector_4_compare (vector_4 * vector_a, vector_4 * vector_b) {
|
||||
if ((vector_a->x == vector_b->x) && (vector_a->y == vector_b->y) && (vector_a->z == vector_b->z) && (vector_a->w == vector_b->w)) {
|
||||
return (true);
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return dot product of two 2D, 3D or 4D vectors.
|
||||
|
||||
static real vector_2_dot_product (vector_2 * vector_a, vector_2 * vector_b) {
|
||||
return (vector_a->x * vector_b->x + vector_a->y * vector_b->y);
|
||||
}
|
||||
|
||||
static real vector_3_dot_product (vector_3 * vector_a, vector_3 * vector_b) {
|
||||
return (vector_a->x * vector_b->x + vector_a->y * vector_b->y + vector_a->z * vector_b->z);
|
||||
}
|
||||
|
||||
static real vector_4_dot_product (vector_4 * vector_a, vector_4 * vector_b) {
|
||||
return (vector_a->x * vector_b->x + vector_a->y * vector_b->y + vector_a->z * vector_b->z + vector_a->w * vector_b->w);
|
||||
}
|
||||
|
||||
/// Return cross product of two 2D vectors.
|
||||
|
||||
static real vector_2_cross_product (vector_2 * vector_a, vector_2 * vector_b) {
|
||||
return (vector_a->x * vector_b->y - vector_a->y * vector_b->x);
|
||||
}
|
||||
|
||||
/// Return cross product of two 3D vectors.
|
||||
|
||||
static vector_3 * vector_3_cross_product (vector_3 * destination, vector_3 * source) {
|
||||
destination->x = destination->y * source->z - destination->z * source->y;
|
||||
destination->y = destination->z * source->x - destination->x * source->z;
|
||||
destination->z = destination->x * source->y - destination->y * source->x;
|
||||
|
||||
return (destination);
|
||||
}
|
||||
164
xrena.h
Normal file
164
xrena.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/// __ ___ __ ___ _ __ __ _
|
||||
/// \ \/ / '__/ _ \ '_ \ / _` |
|
||||
/// > <| | | __/ | | | (_| |
|
||||
/// /_/\_\_| \___|_| |_|\__,_|
|
||||
///
|
||||
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
||||
///
|
||||
/// xolatile@chud.cyou - xrena - Probably the most minimalistic arena allocator possible, and undoubtedly evil in implementation details.
|
||||
///
|
||||
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
||||
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
||||
///
|
||||
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
||||
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
||||
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
||||
|
||||
/// Description
|
||||
///
|
||||
/// Xrena, extremely small header only library serving as arena allocator, with one global variable.In order to use it, include this header file,
|
||||
/// there's no macro for including implementation (like stb libraries), this is for projects that have only one C source file, and one or more C
|
||||
/// header files. I'll provide minimal examples below.
|
||||
|
||||
/// Maximum size for single memory "allocation", if you're making a parser, you can use as low as 8 or 16, but as soon as you start working with
|
||||
/// bigger structures, images or models, you need this to be higher value, for example 64 * 1024 * 1024 (loading 4k textures). If you don't
|
||||
/// understand how to use this macro, turn off your machine and read some books, or alternatively, fuck around until you find out.
|
||||
|
||||
#ifndef arena_block_limit
|
||||
#define arena_block_limit (1024 * 1024)
|
||||
#endif
|
||||
|
||||
/// Structure and global variable definition, you shouldn't ever modify this, functions below cover that task.
|
||||
|
||||
static struct {
|
||||
caliber block_count;
|
||||
caliber block_limit;
|
||||
struct {
|
||||
caliber count;
|
||||
caliber capacity;
|
||||
character * buffer;
|
||||
} * * block_array;
|
||||
} * arena_memory = null;
|
||||
|
||||
/// Warning: Local function! You don't need to use this at all, it's covered by other functions, don't worry about it.
|
||||
///
|
||||
/// This function will initialize the state of variable 'arena_memory', or extend it's size once memory is filled.
|
||||
|
||||
static procedure arena_begin_or_widen (none) {
|
||||
caliber current = ++arena_memory->block_count - 1;
|
||||
|
||||
arena_memory->block_limit = arena_block_limit;
|
||||
|
||||
arena_memory->block_array = reallocate (arena_memory->block_array, arena_memory->block_count * sizeof (* arena_memory->block_array));
|
||||
|
||||
arena_memory->block_array [current] = allocate (sizeof (* arena));
|
||||
|
||||
arena_memory->block_array [current]->buffer = allocate (arena_block_limit);
|
||||
arena_memory->block_array [current]->count = 0;
|
||||
arena_memory->block_array [current]->capacity = arena_block_limit;
|
||||
}
|
||||
|
||||
/// Warning: Local function! You don't need to use this at all, it's covered by other functions, don't worry about it.
|
||||
///
|
||||
/// This function will clean all memory pools from variable 'arena_memory', freeing all memory used by the arena allocator.
|
||||
|
||||
static procedure arena_clean (none) {
|
||||
for (caliber index = 0; index < arena_memory->block_count; ++index) {
|
||||
arena_memory->block_array [index]->buffer = deallocate (arena_memory->block_array [index]->buffer);
|
||||
arena_memory->block_array [index] = deallocate (arena_memory->block_array [index]);
|
||||
}
|
||||
|
||||
arena_memory->block_array = deallocate (arena_memory->block_array);
|
||||
arena_memory = deallocate (arena_memory);
|
||||
}
|
||||
|
||||
/// Now, this is finally a function that you want to use. You want to allocate object of some size, just add that size in arena, it'll return
|
||||
/// you a pointer to that memory location, the same way you'd use 'malloc', and that memory will be zero initialized (unlike 'malloc', just like
|
||||
/// 'calloc'). You don't ever have to worry about freeing memory, if your program has definite exit routine. Internally, it checks if arena
|
||||
/// allocator was initialized, if it was, it'll extend it if there's not enough memory and return that pointer, otherwise, it will initialize it
|
||||
/// and set clean up call at exit.
|
||||
///
|
||||
/// Make an array of 60 integers, they'll all be zero.
|
||||
///
|
||||
/// integer * my_integers = arena_add (60 * sizeof (my_integers));
|
||||
|
||||
static generic * arena_add (caliber size) {
|
||||
caliber current = arena_memory->block_count - 1;
|
||||
|
||||
if (arena == null) {
|
||||
clean_up (arena_clean);
|
||||
|
||||
arena_memory = allocate (sizeof (* arena_memory));
|
||||
|
||||
arena_begin_or_widen ();
|
||||
}
|
||||
|
||||
fatal_failure (size > arena_memory->block_limit, "arena_add: Block limit reached.");
|
||||
|
||||
if (arena_memory->block_array [current]->count + size > arena_memory->block_array [current]->capacity) {
|
||||
arena_begin_or_widen ();
|
||||
}
|
||||
|
||||
arena_memory->block_array [current]->count += size;
|
||||
|
||||
return ((generic *) & arena_memory->block_array [current]->buffer [arena_memory->block_array [current]->count - size]);
|
||||
}
|
||||
|
||||
/// Add null terminated string to arena memory.
|
||||
///
|
||||
/// character * my_token = arena_add_string (parsed_token);
|
||||
|
||||
static character * arena_add_string (character * string) {
|
||||
character * pointer = arena_add (string_length (string) * sizeof (pointer));
|
||||
|
||||
string_copy (pointer, string);
|
||||
|
||||
return (pointer);
|
||||
}
|
||||
|
||||
/// Add raw memory of certain size to arena memory.
|
||||
///
|
||||
/// generic * my_model = arena_add_memory (raw_model_data, size_of_model_data);
|
||||
|
||||
static generic * arena_add_memory (generic * memory, caliber size) {
|
||||
generic * pointer = arena_add (size);
|
||||
|
||||
memory_copy (pointer, memory, size);
|
||||
|
||||
return (pointer);
|
||||
}
|
||||
|
||||
/// Add file data from certain path, specify file flags (similar to 'open' system call) and set if you want it to be null terminated.
|
||||
///
|
||||
/// generic * my_binary_file = arena_add_file ("foo.bin", file_flag_read, false);
|
||||
/// character * my_text_file = arena_add_file ("foo.txt", file_flag_read, true);
|
||||
|
||||
static character * arena_add_file (character * path, integer flag, boolean null_terminate) {
|
||||
integer file = -1;
|
||||
caliber size = 0;
|
||||
character * data = null;
|
||||
|
||||
file = file_open (path, flag);
|
||||
size = file_size (path) + (caliber) null_terminate;
|
||||
data = arena_add (size);
|
||||
|
||||
file_read (file, data, size - (caliber) null_terminate);
|
||||
|
||||
file = file_close (file);
|
||||
|
||||
return (data);
|
||||
}
|
||||
|
||||
/// Simple utility function that returns how many bytes have been added to arena allocator.
|
||||
///
|
||||
/// print ("So far I used %l bytes of memory...\n", arena_usage ());
|
||||
|
||||
static caliber arena_usage (none) {
|
||||
caliber usage = 0;
|
||||
|
||||
for (caliber block = 0; block < arena_memory->block_count; ++block) {
|
||||
usage += arena_memory->block_array [block]->count;
|
||||
}
|
||||
|
||||
return (usage);
|
||||
}
|
||||
238
xyntax.h
Normal file
238
xyntax.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/// _
|
||||
/// __ ___ _ _ __ | |_ __ ___ __
|
||||
/// \ \/ / | | | '_ \| __/ _` \ \/ /
|
||||
/// > <| |_| | | | | || (_| |> <
|
||||
/// /_/\_\\__, |_| |_|\__\__,_/_/\_\
|
||||
/// |___/
|
||||
///
|
||||
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
||||
///
|
||||
/// xolatile@chud.cyou - xyntax - Tiny, unsafe and somewhat insane unity header for generic syntax definition.
|
||||
///
|
||||
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
||||
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
||||
///
|
||||
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
||||
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
||||
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
||||
|
||||
/// Description
|
||||
///
|
||||
/// Xyntax, the most minimal text parser that can deal with syntax highlighting that I could've come up with, and the most generic name for it
|
||||
/// also, it's rather slow, but if you're creating heavy duty program, you'd use heavy duty library for it. This library has only one header, so
|
||||
/// it's easy to incorporate it into existing projects. If you want to see how it is used, check out simple examples below, if you want more
|
||||
/// robust example, check out my other programs, Xarbon and Xighlight.
|
||||
///
|
||||
/// For start, you want to include this header file, there's no macro for including implementation (like stb libraries), this is for projects
|
||||
/// that have only one C source file, and one or more C header files. Then make global or local variable 'syntax_structure * whatever_syntax'
|
||||
/// defined below, initialize it, define the rules, then in main loop select rule, do whatever you wanted, then deinitialize the structure. It's
|
||||
/// simple, I'll provide minimal examples below.
|
||||
|
||||
/// Structure for single syntax definition (array of rules), if you want to parse multiple languages simultaneously, use an array.
|
||||
///
|
||||
/// syntax_structure * syntax = null;
|
||||
|
||||
typedef struct {
|
||||
natural count; /// Count of syntax rules used, maximum is set with limit below, if limit is 0, it'll allocate it dynamically.
|
||||
natural limit; /// Preallocation limit for syntax rules, hardcode it if you don't want this to allocate memory dynamically.
|
||||
boolean * enrange; /// Enrange rule, set to true if you want to begin matching by any character from 'begin' string below.
|
||||
boolean * derange; /// Derange rule, set to true if you want to end matching by any character from 'end' string below.
|
||||
character * * begin; /// String containing set of characters or full string for start of matching, correlating to 'enrange' above.
|
||||
character * * end; /// String containing set of characters or full string for end of matching, correlating to 'derange' above.
|
||||
character * escape; /// Escape character, which will skip one cycle in selection loop, then continue matching for 'end' string.
|
||||
natural * colour; /// Colour for matched array of characters, can be anything, enumerated, literal, hardcoded...
|
||||
natural * effect; /// Effect for matched array of characters, can be anything, enumerated, literal, hardcoded...
|
||||
} syntax_structure;
|
||||
|
||||
/// Initialize syntax structure before calling other functions that take it as an argument, set 'limit' to 0 if you want dynamic array of rules.
|
||||
///
|
||||
/// syntax = syntax_initialize (0);
|
||||
|
||||
static syntax_structure * syntax_initialize (natural limit) {
|
||||
syntax_structure * syntax = allocate (sizeof (* syntax));
|
||||
|
||||
syntax->limit = limit;
|
||||
|
||||
if (limit != 0) {
|
||||
syntax->enrange = allocate (syntax->limit * sizeof (* syntax->enrange));
|
||||
syntax->derange = allocate (syntax->limit * sizeof (* syntax->derange));
|
||||
syntax->begin = allocate (syntax->limit * sizeof (* syntax->begin));
|
||||
syntax->end = allocate (syntax->limit * sizeof (* syntax->end));
|
||||
syntax->escape = allocate (syntax->limit * sizeof (* syntax->escape));
|
||||
syntax->colour = allocate (syntax->limit * sizeof (* syntax->colour));
|
||||
syntax->effect = allocate (syntax->limit * sizeof (* syntax->effect));
|
||||
}
|
||||
|
||||
return (syntax);
|
||||
}
|
||||
|
||||
/// Deinitialize syntax structure after using it, in order to avoid memory leaks.
|
||||
///
|
||||
/// syntax = syntax_deinitialize (syntax);
|
||||
|
||||
static syntax_structure * syntax_deinitialize (syntax_structure * syntax) {
|
||||
for (natural index = 0; index < syntax->count; ++index) {
|
||||
syntax->begin [index] = deallocate (syntax->begin [index]);
|
||||
syntax->end [index] = deallocate (syntax->end [index]);
|
||||
}
|
||||
|
||||
syntax->enrange = deallocate (syntax->enrange);
|
||||
syntax->derange = deallocate (syntax->derange);
|
||||
syntax->begin = deallocate (syntax->begin);
|
||||
syntax->end = deallocate (syntax->end);
|
||||
syntax->escape = deallocate (syntax->escape);
|
||||
syntax->colour = deallocate (syntax->colour);
|
||||
syntax->effect = deallocate (syntax->effect);
|
||||
|
||||
return (deallocate (syntax));
|
||||
}
|
||||
|
||||
/// Define single syntax rule, which will be added into array part of syntax structure, return value is index into that array.
|
||||
///
|
||||
/// Take a look into few simple examples of defining some simplified rules of C programming language.
|
||||
/// Two examples below show how to define multiline comments and strings, since these have priority, both enrange and derange are false.
|
||||
///
|
||||
/// syntax_define (syntax, false, false, "/*", "*/", '\\', 1, 0);
|
||||
/// syntax_define (syntax, false, false, "\"", "\"", '\\', 2, 0);
|
||||
///
|
||||
/// Now we're defining syntax rule for one keyword, static, notice that end string contaings separator characters because derange is true.
|
||||
///
|
||||
/// syntax_define (syntax, false, true, "static", "()[]{}.,:;<=>+*-/%!&~^?| \t\r\n", '\0', 3, 0);
|
||||
///
|
||||
/// You can define brackets and operator characters separately, or if you want to, you can define some of them separately again.
|
||||
///
|
||||
/// syntax_define (syntax, true, false, "()[]{}", "", '\0', 4, 0);
|
||||
/// syntax_define (syntax, true, false, ".,:;<=>+*-/%!&~^?|", "", '\0', 5, 0);
|
||||
///
|
||||
/// And lastly, we can define number selection like this below, by setting both enrange and derange as false.
|
||||
///
|
||||
/// syntax_define (syntax, true, true, "0123456789", "()[]{}.,:;<=>+*-/%!&~^?| \t\r\n", '\0', 6, 0);
|
||||
///
|
||||
/// I hope this is pretty clear, if you want to select a number, you start by matching any of digits provided above, and you end matching that
|
||||
/// number by any character from 'end' string, if you want to support floating point numbers, you'd exclude '.' character, or alternatively add
|
||||
/// letters f, u, l and whatever else your language supports (like in C/C++). However, this approach is too weak for detecting syntax errors,
|
||||
/// you shouldn't use this library for robust linter or parser.
|
||||
|
||||
static natural syntax_define (syntax_structure * syntax, boolean enrange, boolean derange, character * begin, character * end, character escape,
|
||||
natural colour, natural effect) {
|
||||
++syntax->count;
|
||||
|
||||
natural current = syntax->count - 1;
|
||||
|
||||
fatal_failure (begin == null, "syntax_define: Begin string is null pointer.");
|
||||
fatal_failure (end == null, "syntax_define: End string is null pointer.");
|
||||
|
||||
fatal_failure (syntax->count >= syntax->limit, "syntax_define: Reached the hardcoded limit.");
|
||||
|
||||
if (syntax->limit == 0) {
|
||||
syntax->enrange = reallocate (syntax->enrange, syntax->count * sizeof (* syntax->enrange));
|
||||
syntax->derange = reallocate (syntax->derange, syntax->count * sizeof (* syntax->derange));
|
||||
syntax->begin = reallocate (syntax->begin, syntax->count * sizeof (* syntax->begin));
|
||||
syntax->end = reallocate (syntax->end, syntax->count * sizeof (* syntax->end));
|
||||
syntax->escape = reallocate (syntax->escape, syntax->count * sizeof (* syntax->escape));
|
||||
syntax->colour = reallocate (syntax->colour, syntax->count * sizeof (* syntax->colour));
|
||||
syntax->effect = reallocate (syntax->effect, syntax->count * sizeof (* syntax->effect));
|
||||
}
|
||||
|
||||
syntax->begin [current] = allocate ((string_length (begin) + 1) * sizeof (* * syntax->begin));
|
||||
syntax->end [current] = allocate ((string_length (end) + 1) * sizeof (* * syntax->end));
|
||||
|
||||
syntax->enrange [current] = enrange;
|
||||
syntax->derange [current] = derange;
|
||||
syntax->escape [current] = escape;
|
||||
syntax->colour [current] = colour;
|
||||
syntax->effect [current] = effect;
|
||||
|
||||
string_copy (syntax->begin [current], begin);
|
||||
string_copy (syntax->end [current], end);
|
||||
|
||||
return (current);
|
||||
}
|
||||
|
||||
/// After all syntax definitions have been defined, call this function inside your main loop, return value is index of selected rule.
|
||||
///
|
||||
/// Now, imagine that 'buffer' is file you've loaded into memory, you have declared natural numbers 'offset', 'length' and 'select', and you've
|
||||
/// properly initialized syntax structure 'syntax', defined its rules for wanted language(s), simple main loop would look like this:
|
||||
///
|
||||
/// for (offset = 0; buffer [offset] != '\0'; offset += length) {
|
||||
/// /// Notice that we're not incrementing 'offset', we're increasing it by 'length'.
|
||||
/// select = syntax_select (syntax, & buffer [offset], & length);
|
||||
/// if (select >= syntax->count) {
|
||||
/// /// Syntax definition is incomplete, unknown sequence has been detected, either print nothing, or print default.
|
||||
/// } else {
|
||||
/// /// Print string of 'length', at '& buffer [offset]', using 'syntax->colour [select]' and 'syntax->effect [select]'.
|
||||
/// /// Strings here aren't null terminated, you want to print sized string.
|
||||
/// }
|
||||
/// }
|
||||
|
||||
static natural syntax_select (syntax_structure * syntax, character * string, natural * length) {
|
||||
natural offset = 0;
|
||||
natural subset = 0;
|
||||
natural select = 0;
|
||||
|
||||
for (; select != syntax->count; ++select) {
|
||||
caliber begin_length = string_length (syntax->begin [select]);
|
||||
|
||||
if (syntax->enrange [select] == false) {
|
||||
if (syntax->derange [select] == false) {
|
||||
if (string_compare_limit (string, syntax->begin [select], begin_length) == true) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ((string_compare_limit (string, syntax->begin [select], begin_length) == true)
|
||||
&& (character_compare_array (string [offset + begin_length], syntax->end [select]) == true)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (subset = 0; subset != begin_length; ++subset) {
|
||||
if (string [offset] == syntax->begin [select] [subset]) {
|
||||
goto selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selected:
|
||||
|
||||
if (select >= syntax->count) {
|
||||
* length = 1;
|
||||
|
||||
return (syntax->count);
|
||||
}
|
||||
|
||||
caliber end_length = string_length (syntax->end [select]);
|
||||
|
||||
for (offset = 1; string [offset - 1] != character_null; ++offset) {
|
||||
if (string [offset] == syntax->escape [select]) {
|
||||
++offset;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (syntax->derange [select] == true) {
|
||||
subset = 0;
|
||||
if (end_length == 0) {
|
||||
break;
|
||||
} do {
|
||||
if (string [offset] == syntax->end [select] [subset]) {
|
||||
* length = offset;
|
||||
goto finished;
|
||||
}
|
||||
} while (++subset != end_length);
|
||||
} else {
|
||||
if (end_length != 0) {
|
||||
if (string_compare_limit (& string [offset], syntax->end [select], end_length)) {
|
||||
* length = offset + end_length;
|
||||
return (select);
|
||||
}
|
||||
} else {
|
||||
* length = 1;
|
||||
return (select);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finished:
|
||||
|
||||
return (select);
|
||||
}
|
||||
Reference in New Issue
Block a user