Initial Commit

This commit is contained in:
Medusa Slockbower 2025-05-25 22:36:59 -04:00
commit a6442e1945
64 changed files with 20486 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/build/
/docs/

113
CMakeLists.txt Normal file
View File

@ -0,0 +1,113 @@
cmake_minimum_required(VERSION 3.30)
project(fennec)
set(CMAKE_CXX_STANDARD 26)
set(CMAKE_C_STANDARD 26)
include_directories(include)
add_library(fennec STATIC
# CORE =================================================================================================================
include/fennec/core/engine.h source/core/engine.cpp
# CONTAINERS ===========================================================================================================
include/fennec/containers/array.h
include/fennec/containers/dynarray.h
# LANG =================================================================================================================
include/fennec/lang/constants.h
include/fennec/lang/conditional_types.h
include/fennec/lang/intrinsics.h
include/fennec/lang/limits.h
include/fennec/lang/sequences.h
include/fennec/lang/type_traits.h
include/fennec/lang/type_transforms.h
include/fennec/lang/types.h
include/fennec/lang/utility.h
include/fennec/lang/detail/__type_traits.h
# MEMORY ===============================================================================================================
include/fennec/memory/allocator.h
include/fennec/memory/bits.h
include/fennec/memory/memory.h
include/fennec/memory/new.h
source/memory/new.cpp
# MATH =================================================================================================================
include/fennec/math/math.h
include/fennec/math/scalar.h
include/fennec/math/vector.h
include/fennec/math/vector_base.h
include/fennec/math/vector_traits.h
include/fennec/math/vector_storage.h
include/fennec/math/swizzle.h
include/fennec/math/swizzle_storage.h
include/fennec/math/matrix.h
include/fennec/math/common.h
include/fennec/math/exponential.h
include/fennec/math/geometric.h
include/fennec/math/trigonometric.h
include/fennec/math/relational.h
include/fennec/math/detail/__fwd.h
include/fennec/math/detail/__types.h
include/fennec/math/detail/__vector_traits.h
)
add_subdirectory(metaprogramming)
add_dependencies(fennec fennecdocs metaprogramming)
if(MSVC)
add_compile_options("/W4" "/WX")
else()
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror")
endif()
target_compile_options(fennec PUBLIC "-mavx" "-mavx2" "-mavx512f")
target_link_options(fennec PRIVATE "-nostdlib" "-nocstdlib")
add_subdirectory(test)
# DOXYGEN ==============================================================================================================
# https://vicrucann.github.io/tutorials/quick-cmake-doxygen/
find_package(Doxygen)
if(DOXYGEN_FOUND)
get_filename_component(DOXYGEN_PROJECT_NAME ${PROJECT_SOURCE_DIR} NAME)
set(DOXYGEN_CONFIG_IN "${PROJECT_SOURCE_DIR}/doxy/Doxyfile.in")
set(DOXYGEN_CONFIG_OUT "${PROJECT_SOURCE_DIR}/doxy/Doxyfile")
configure_file(${DOXYGEN_CONFIG_IN} ${DOXYGEN_CONFIG_OUT} @ONLY)
message("Doxygen Build Started.")
add_custom_target(fennecdocs ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG_OUT}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Generating Doxygen Documentation"
VERBATIM)
add_custom_target(fennecdocs-clean ALL
COMMAND rm -r "${PROJECT_SOURCE_DIR}/docs/"
COMMENT "Cleaning Doxygen Documentation"
VERBATIM)
else()
message("Doxygen not found.")
endif()

674
LICENSE Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
fennec, a free and open source game engine.
Copyright (C) 2024 Medusa Slockbower
This program is free software: 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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
fennec Copyright (C) 2024 Medusa Slockbower
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

110
README.md Normal file
View File

@ -0,0 +1,110 @@
# fennec
*a free and open source game engine*
## Table of Contents
1. [Introduction](#introduction)
2. [Building from Source](#building-from-source)
1. [Building from Terminal](#building-from-terminal)
2. [Building on Windows](#building-on-windows)
3. [Running the Test Suite](#running-the-test-suite)
<br>
<br>
## Introduction
fennec is designed to be a general purpose, educational game engine.
Interfacing with the API in C++ follows the [GNU Coding Standards](https://www.gnu.org/prep/standards/html_node/index.html).
<br>
Some main areas where the engine strays from the GNU standard includes the following:
- [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html).
fennec provides an implementation for X11, however it does not use the GTK toolkit.
<br>
## Building from Source
fennec uses the CMake build system. The CMake build script provides several
targets for building parts of the engine.
| Target | Description |
|------------------------|----------------------------------------------------------------------------------------|
| fennec | The main engine target. |
| fennec-metaprogramming | Generate metaprogramming info for the fennec library. A dependency of the main engine. |
| fennecdocs | Generate html documentation for the engine. Requires Doxygen. |
| fennecdocs-clean | Cleans the generated html documentation files. |
| fennec-test | Test suite for verifying engine functionality. |
<br>
Using an IDE will streamline the build process for you and add additional configuration
options. Eclipse, Visual Studio, and CLion provide built-in support for CMake. VSCode
is also a viable IDE but involves some extra setup.
<br>
### Building from Terminal
`build.sh` provides profiles for building the main engine. Run `./build.sh --help`
for more info.
By default, the CMake generator
used is Ninja, which requires Ninja to be installed. You can modify the
build scripts to use another build manager, see the [CMake documentation
for available generators](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
<br>
### Building on Windows
The bash script can be run natively on Windows when WSL is enabled. You do not
need to run the script in WSL, simply use the "bash" command in Command Prompt
or PowerShell. It requires CMake and a C/C++ compiler to be installed and
configured in the PATH environment variable.
Fore more details, [see this blog post](https://blogs.windows.com/windows-insider/2016/04/06/announcing-windows-10-insider-preview-build-14316/)
for Windows Build 14316.
Otherwise, follow the sequence of commands provided in the bash script.
```console
mkdir -p build/<profile>
cd ./build/<profile>
cmake -G Ninja -DCMAKE_BUILD_TYPE=<profile> -S ../.. -B .
cmake --build . --target fennec
```
The value of `<profile>` may be one of the following:
| Profile | Description |
|----------------|----------------------------------------------------------------------------------|
| Debug | Build in debug mode, provides full debugging information to use with a debugger. |
| Release | Build in release mode, provides full optimizations, eliminating debug info. |
| RelWithDebInfo | Build in release mode with extra debug info, provides partial optimizations. |
| MinSizeRel | Build in release mode but optimizing for minimum binary size. |
<br>
If you would like to use Visual Studio without CMake, you can use the build
script to generate a Visual Studio project for the source. For a list of available
Visual Studio generators, [see this section](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html).
Running the following command will generate the Visual Studio project.
```commandline
cmake -G "Visual Studio 17 2022" -A x64
```
<br>
<br>
## Running the Test Suite
`test.sh` provides profiles for building the test suite and executes them.

111
build.sh Executable file
View File

@ -0,0 +1,111 @@
## =====================================================================================================================
## fennec, a free and open source game engine
## Copyright © 2025 Medusa Slockbower
##
## This program is free software: 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
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <https://www.gnu.org/licenses/>.
## =====================================================================================================================
## Help ================================================================================================================
Help()
{
echo "Bash script for building fennec from source."
echo
echo "GNU long options:"
echo "--help (-h) = Print this help info."
echo "--debug (-d) = Build in debug mode, provides full debugging information to use with a debugger."
echo "--release (-r) = Build in release mode, provides full optimizations, eliminating debug info."
echo "--relwithdebinfo (-i) = Build in release mode with extra debug info, provides partial optimizations."
echo "--minsizerel (-m) = Build in release mode but optimizing for minimum binary size."
echo "--all (-a) = Build all profiles."
}
## Build Profiles ======================================================================================================
Debug()
{
mkdir -p build/debug
cd ./build/debug
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -S ../.. -B .
cmake --build . --target fennec
cd ../..
}
Release()
{
mkdir -p build/release
cd ./build/release
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -S ../.. -B .
cmake --build . --target fennec
cd ../..
}
RelWithDebInfo()
{
mkdir -p build/relwithdebinfo
cd ./build/relwithdebinfo
cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -S ../.. -B .
cmake --build . --target fennec
cd ../..
}
MinSizeRel()
{
mkdir -p build/minsizerel
cd ./build/minsizerel
cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel -S ../.. -B .
cmake --build . --target fennec
cd ../..
}
All()
{
Debug
Release
RelWithDebInfo
MinSizeRel
}
# Main Program =========================================================================================================
while [ "${1:-}" != '' ]; do
case "$1" in
'--debug' | '-d')
Debug
exit;;
'--release' | '-r')
Release
exit;;
'--relwithdebinfo' | '-i')
RelWithDebInfo
exit;;
'--minsizerel' | '-m')
MinSizeRel
exit;;
'--all' | '-a')
All
exit;;
*)
echo "Error: Invalid option"
exit;;
esac
done

2868
doxy/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

2868
doxy/Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

289
doxy/custom.css Normal file
View File

@ -0,0 +1,289 @@
html {
/* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */
--primary-color: #1779c4;
--primary-dark-color: #335c80;
--primary-light-color: #70b1e9;
/* page base colors */
--page-background-color: #ffffff;
--page-foreground-color: #2f4153;
--page-secondary-foreground-color: #6f7e8e;
--separator-color: #dedede;
--side-nav-background: #fbfbfb;
--code-background: #f5f5f5;
--tablehead-background: #f1f1f1;
/* blockquote colors */
--blockquote-background: #f8f9fa;
--blockquote-foreground: #636568;
/* colors for various content boxes: @warning, @note, @deprecated @bug */
--warning-color: #faf3d8;
--warning-color-dark: #f3a600;
--warning-color-darker: #5f4204;
--note-color: #e4f3ff;
--note-color-dark: #1879C4;
--note-color-darker: #274a5c;
--todo-color: #e4dafd;
--todo-color-dark: #5b2bdd;
--todo-color-darker: #2a0d72;
--deprecated-color: #ecf0f3;
--deprecated-color-dark: #5b6269;
--deprecated-color-darker: #43454a;
--bug-color: #f8d1cc;
--bug-color-dark: #b61825;
--bug-color-darker: #75070f;
--invariant-color: #d8f1e3;
--invariant-color-dark: #44b86f;
--invariant-color-darker: #265532;
/* fragment colors */
--fragment-background: #F8F9FA;
--fragment-foreground: #37474F;
--fragment-keyword: #bb6bb2;
--fragment-keywordtype: #8258b3;
--fragment-keywordflow: #d67c3b;
--fragment-token: #438a59;
--fragment-comment: #969696;
--fragment-link: #5383d6;
--fragment-preprocessor: #46aaa5;
--fragment-linenumber-color: #797979;
--fragment-linenumber-background: #f4f4f5;
--fragment-linenumber-border: #e3e5e7;
--fragment-math: #335c80;
--fragment-lineheight: 20px;
/* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */
--border-radius-large: 8px;
--border-radius-small: 4px;
--border-radius-medium: 6px;
/* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */
--spacing-small: 5px;
--spacing-medium: 10px;
--spacing-large: 16px;
/* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */
--box-shadow: 0 2px 8px 0 rgba(0,0,0,.075);
--odd-color: rgba(0,0,0,.028);
/* font-families. will affect all text on the website
* font-family: the normal font for text, headlines, menus
* font-family-monospace: used for preformatted text in memtitle, code, fragments
*/
--font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
--font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
/* font sizes */
--page-font-size: medium;
--navigation-font-size: medium;
--toc-font-size: medium;
--code-font-size: medium; /* affects code, fragment */
--title-font-size: larger;
/* content text properties. These only affect the page content, not the navigation or any other ui elements */
--content-line-height: 27px;
/* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/
--content-maxwidth: 1050px;
--table-line-height: 24px;
--toc-sticky-top: var(--spacing-medium);
--toc-width: 200px;
--toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px);
/* table colors */
--tablehead-foreground: var(--page-foreground-color);
/* menu-display: block | none
* Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible.
* `GENERATE_TREEVIEW` MUST be enabled!
*/
--menu-display: block;
--menu-focus-foreground: var(--page-background-color);
--menu-focus-background: var(--primary-color);
--menu-selected-background: rgba(0,0,0,.05);
--header-background: var(--page-background-color);
--header-foreground: var(--page-foreground-color);
/* searchbar colors */
--searchbar-background: var(--side-nav-background);
--searchbar-foreground: var(--page-foreground-color);
/* searchbar size
* (`searchbar-width` is only applied on screens >= 768px.
* on smaller screens the searchbar will always fill the entire screen width) */
--searchbar-height: 33px;
--searchbar-width: 210px;
--searchbar-border-radius: var(--searchbar-height);
/* code block colors */
--code-foreground: var(--page-foreground-color);
/* sidebar navigation (treeview) colors */
--side-nav-foreground: var(--page-foreground-color);
--side-nav-arrow-opacity: 0;
--side-nav-arrow-hover-opacity: 0.9;
--toc-background: var(--side-nav-background);
--toc-foreground: var(--side-nav-foreground);
/* height of an item in any tree / collapsible table */
--tree-item-height: 30px;
--memname-font-size: var(--code-font-size);
--memtitle-font-size: medium;
--webkit-scrollbar-size: 7px;
--webkit-scrollbar-padding: 4px;
--webkit-scrollbar-color: var(--separator-color);
--animation-duration: .12s
}
@media screen and (max-width: 767px) {
html {
--page-font-size: medium;
--navigation-font-size: medium;
--toc-font-size: medium;
--code-font-size: medium; /* affects code, fragment */
--title-font-size: larger;
}
}
@media (prefers-color-scheme: dark) {
html:not(.light-mode) {
color-scheme: dark;
--primary-color: #1982d2;
--primary-dark-color: #86a9c4;
--primary-light-color: #4779ac;
--page-background-color: #1C1D1F;
--page-foreground-color: #d2dbde;
--page-secondary-foreground-color: #859399;
--separator-color: #38393b;
--side-nav-background: #252628;
--code-background: #2a2c2f;
--tablehead-background: #2a2c2f;
--blockquote-background: #222325;
--blockquote-foreground: #7e8c92;
--warning-color: #3b2e04;
--warning-color-dark: #f1b602;
--warning-color-darker: #ceb670;
--note-color: #163750;
--note-color-dark: #1982D2;
--note-color-darker: #dcf0fa;
--todo-color: #2a2536;
--todo-color-dark: #7661b3;
--todo-color-darker: #ae9ed6;
--deprecated-color: #2e323b;
--deprecated-color-dark: #738396;
--deprecated-color-darker: #abb0bd;
--bug-color: #2e1917;
--bug-color-dark: #ad2617;
--bug-color-darker: #f5b1aa;
--invariant-color: #303a35;
--invariant-color-dark: #76ce96;
--invariant-color-darker: #cceed5;
--fragment-background: #282c34;
--fragment-foreground: #dbe4eb;
--fragment-keyword: #cc99cd;
--fragment-keywordtype: #ab99cd;
--fragment-keywordflow: #e08000;
--fragment-token: #7ec699;
--fragment-comment: #999999;
--fragment-link: #98c0e3;
--fragment-preprocessor: #65cabe;
--fragment-linenumber-color: #cccccc;
--fragment-linenumber-background: #35393c;
--fragment-linenumber-border: #1f1f1f;
--fragment-math: #86a9c4;
--box-shadow: 0 2px 8px 0 rgba(0,0,0,.35);
--odd-color: rgba(100,100,100,.06);
--menu-selected-background: rgba(0,0,0,.4);
}
}
/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */
html.dark-mode {
color-scheme: dark;
--primary-color: #1982d2;
--primary-dark-color: #86a9c4;
--primary-light-color: #4779ac;
--box-shadow: 0 2px 8px 0 rgba(0,0,0,.30);
--odd-color: rgba(100,100,100,.06);
--menu-selected-background: rgba(0,0,0,.4);
--page-background-color: #1C1D1F;
--page-foreground-color: #d2dbde;
--page-secondary-foreground-color: #859399;
--separator-color: #38393b;
--side-nav-background: #252628;
--code-background: #2a2c2f;
--tablehead-background: #2a2c2f;
--blockquote-background: #222325;
--blockquote-foreground: #7e8c92;
--warning-color: #3b2e04;
--warning-color-dark: #f1b602;
--warning-color-darker: #ceb670;
--note-color: #163750;
--note-color-dark: #1982D2;
--note-color-darker: #dcf0fa;
--todo-color: #2a2536;
--todo-color-dark: #7661b3;
--todo-color-darker: #ae9ed6;
--deprecated-color: #2e323b;
--deprecated-color-dark: #738396;
--deprecated-color-darker: #abb0bd;
--bug-color: #2e1917;
--bug-color-dark: #ad2617;
--bug-color-darker: #f5b1aa;
--invariant-color: #303a35;
--invariant-color-dark: #76ce96;
--invariant-color-darker: #cceed5;
--fragment-background: #282c34;
--fragment-foreground: #dbe4eb;
--fragment-keyword: #cc99cd;
--fragment-keywordtype: #ab99cd;
--fragment-keywordflow: #e08000;
--fragment-token: #7ec699;
--fragment-comment: #999999;
--fragment-link: #98c0e3;
--fragment-preprocessor: #65cabe;
--fragment-linenumber-color: #cccccc;
--fragment-linenumber-background: #35393c;
--fragment-linenumber-border: #1f1f1f;
--fragment-math: #86a9c4;
}
.MathJax {
color: var(--fragment-math)
}
td.odd_c {
background-color: var(--odd-color)
}

View File

@ -0,0 +1,157 @@
/**
Doxygen Awesome
https://github.com/jothepro/doxygen-awesome-css
MIT License
Copyright (c) 2021 - 2023 jothepro
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated docs 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.
*/
class DoxygenAwesomeDarkModeToggle extends HTMLElement {
// SVG icons from https://fonts.google.com/icons
// Licensed under the Apache 2.0 license:
// https://www.apache.org/licenses/LICENSE-2.0.html
static lightModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FCBF00"><rect fill="none" height="24" width="24"/><circle cx="12" cy="12" opacity=".3" r="3"/><path d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"/></svg>`
static darkModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FE9700"><rect fill="none" height="24" width="24"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27 C17.45,17.19,14.93,19,12,19c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z" opacity=".3"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"/></svg>`
static title = "Toggle Light/Dark Mode"
static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode"
static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode"
static _staticConstructor = function() {
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference)
// Update the color scheme when the browsers preference changes
// without user interaction on the website.
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
})
// Update the color scheme when the tab is made visible again.
// It is possible that the appearance was changed in another tab
// while this tab was in the background.
document.addEventListener("visibilitychange", visibilityState => {
if (document.visibilityState === 'visible') {
DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
}
});
}()
static init() {
$(function() {
$(document).ready(function() {
const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle')
toggleButton.title = DoxygenAwesomeDarkModeToggle.title
toggleButton.updateIcon()
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
toggleButton.updateIcon()
})
document.addEventListener("visibilitychange", visibilityState => {
if (document.visibilityState === 'visible') {
toggleButton.updateIcon()
}
});
$(document).ready(function(){
document.getElementById("MSearchBox").parentNode.appendChild(toggleButton)
})
$(window).resize(function(){
document.getElementById("MSearchBox").parentNode.appendChild(toggleButton)
})
})
})
}
constructor() {
super();
this.onclick=this.toggleDarkMode
}
/**
* @returns `true` for dark-mode, `false` for light-mode system preference
*/
static get systemPreference() {
return window.matchMedia('(prefers-color-scheme: dark)').matches
}
/**
* @returns `true` for dark-mode, `false` for light-mode user preference
*/
static get userPreference() {
return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) ||
(DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey))
}
static set userPreference(userPreference) {
DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference
if(!userPreference) {
if(DoxygenAwesomeDarkModeToggle.systemPreference) {
localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true)
} else {
localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)
}
} else {
if(!DoxygenAwesomeDarkModeToggle.systemPreference) {
localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true)
} else {
localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)
}
}
DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged()
}
static enableDarkMode(enable) {
if(enable) {
DoxygenAwesomeDarkModeToggle.darkModeEnabled = true
document.documentElement.classList.add("dark-mode")
document.documentElement.classList.remove("light-mode")
} else {
DoxygenAwesomeDarkModeToggle.darkModeEnabled = false
document.documentElement.classList.remove("dark-mode")
document.documentElement.classList.add("light-mode")
}
}
static onSystemPreferenceChanged() {
DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
}
static onUserPreferenceChanged() {
DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
}
toggleDarkMode() {
DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference
this.updateIcon()
}
updateIcon() {
if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) {
this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon
} else {
this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon
}
}
}
customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle);

View File

@ -0,0 +1,40 @@
/**
Doxygen Awesome
https://github.com/jothepro/doxygen-awesome-css
MIT License
Copyright (c) 2021 - 2023 jothepro
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated docs 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.
*/
@media screen and (min-width: 768px) {
#MSearchBox {
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - var(--searchbar-height) - 1px);
}
#MSearchField {
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 66px - var(--searchbar-height));
}
}

View File

@ -0,0 +1,118 @@
/**
Doxygen Awesome
https://github.com/jothepro/doxygen-awesome-css
MIT License
Copyright (c) 2021 - 2023 jothepro
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.
*/
html {
/* side nav width. MUST be = `TREEVIEW_WIDTH`.
* Make sure it is wide enough to contain the page title (logo + title + version)
*/
--side-nav-fixed-width: 335px;
--menu-display: none;
--top-height: 160px;
--toc-sticky-top: -25px;
--toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 25px);
}
#projectname {
white-space: nowrap;
}
@media screen and (min-width: 768px) {
html {
--searchbar-background: var(--page-background-color);
}
#side-nav {
min-width: var(--side-nav-fixed-width);
max-width: var(--side-nav-fixed-width);
top: var(--top-height);
overflow: visible;
}
#nav-tree, #side-nav {
height: calc(100vh - var(--top-height)) !important;
}
#nav-tree {
padding: 0;
}
#top {
display: block;
border-bottom: none;
height: var(--top-height);
margin-bottom: calc(0px - var(--top-height));
max-width: var(--side-nav-fixed-width);
overflow: visible;
background: var(--side-nav-background);
}
#main-nav {
float: left;
padding-right: 0;
z-index: 2;
overflow: visible;
}
.ui-resizable-handle {
cursor: default;
width: 1px !important;
background: var(--separator-color);
box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color);
}
#nav-path {
position: fixed;
right: 0;
left: var(--side-nav-fixed-width);
bottom: 0;
width: auto;
}
#doc-content {
height: calc(100vh - 31px) !important;
padding-bottom: calc(3 * var(--spacing-large));
padding-top: calc(var(--top-height) - 80px);
box-sizing: border-box;
margin-left: var(--side-nav-fixed-width) !important;
}
#MSearchBox {
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)));
}
#MSearchField {
width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px);
}
#MSearchResultsWindow {
left: var(--spacing-medium) !important;
right: auto;
}
}

2680
doxy/doxygen-awesome.css Normal file

File diff suppressed because it is too large Load Diff

17
doxy/footer.html Normal file
View File

@ -0,0 +1,17 @@
<!-- HTML footer for doxygen 1.9.8-->
<!-- start footer part -->
<!--BEGIN GENERATE_TREEVIEW-->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
$navpath
<li class="footer">$generatedby <a href="https://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion </li>
</ul>
</div>
<!--END GENERATE_TREEVIEW-->
<!--BEGIN !GENERATE_TREEVIEW-->
<hr class="footer"/><address class="footer"><small>
$generatedby&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion
</small></address>
<!--END !GENERATE_TREEVIEW-->
</body>
</html>

78
doxy/header.html Normal file
View File

@ -0,0 +1,78 @@
<!-- HTML header for doxygen 1.9.8-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="$langISO">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN FULL_SIDEBAR-->
<script type="text/javascript">var page_layout=1;</script>
<!--END FULL_SIDEBAR-->
<!--END DISABLE_INDEX-->
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview
$search
$mathjax
$darkmode
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
</head>
<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>
<script type="text/javascript">
DoxygenAwesomeDarkModeToggle.init()
</script>
<body>
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN FULL_SIDEBAR-->
<div id="side-nav" class="ui-resizable side-nav-resizable"><!-- do not remove this div, it is closed by doxygen! -->
<!--END FULL_SIDEBAR-->
<!--END DISABLE_INDEX-->
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA-->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<!--BEGIN PROJECT_LOGO-->
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
<!--END PROJECT_LOGO-->
<!--BEGIN PROJECT_NAME-->
<td id="projectalign">
<div id="projectname">$projectname<!--BEGIN PROJECT_NUMBER--><span id="projectnumber">&#160;$projectnumber</span><!--END PROJECT_NUMBER-->
</div>
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
</td>
<!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<!--BEGIN PROJECT_BRIEF-->
<td>
<div id="projectbrief">$projectbrief</div>
</td>
<!--END PROJECT_BRIEF-->
<!--END !PROJECT_NAME-->
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN SEARCHENGINE-->
<!--BEGIN !FULL_SIDEBAR-->
<td>$searchbox</td>
<!--END !FULL_SIDEBAR-->
<!--END SEARCHENGINE-->
<!--END DISABLE_INDEX-->
</tr>
<!--BEGIN SEARCHENGINE-->
<!--BEGIN FULL_SIDEBAR-->
<tr><td colspan="2">$searchbox</td></tr>
<!--END FULL_SIDEBAR-->
<!--END SEARCHENGINE-->
</tbody>
</table>
</div>
<!--END TITLEAREA-->
<!-- end header part -->

1684
doxy/style.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file array.h
/// \brief fennec::array definition & implementation
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_CONTAINERS_ARRAY_H
#define FENNEC_CONTAINERS_ARRAY_H
#include <fennec/lang/types.h>
#include <cassert>
namespace fennec
{
///
///
/// \brief wrapper for fixed size arrays
///
/// \details
/// \tparam ValueT value type
/// \tparam ElemV number of elements
///
///
template<typename ValueT, size_t ElemV>
struct array
{
///
/// \brief backing c-style array handle
ValueT elements[ElemV];
/// \name Element Access
/// @{
///
/// \copydetails array::at(size_t) const
constexpr ValueT& at(size_t i) { static_assert(i < ElemV); assert(i < ElemV); return elements[i]; }
///
/// \brief access specified element, **with bounds checking**
/// \details Returns a reference to the element at \c i
/// \param i index of the element to return
/// \return reference to the requested element
///
/// \par Time-Complexity
/// Constant
///
/// \par Space-Complexity
/// Constant
constexpr const ValueT& at(size_t i) const { static_assert(i < ElemV); assert(i < ElemV); return elements[i]; }
///
/// \copydetails array::operator[](size_t) const
constexpr ValueT& operator[](size_t i) { return elements[i]; }
///
/// \brief access specified element
/// \details Returns a reference to the element at \c i
/// \param i index of the element to return
/// \return reference to the requested element
///
/// \par Time-Complexity
/// Constant
///
/// \par Space-Complexity
/// Constant
constexpr const ValueT& operator[](size_t i) const { return elements[i]; }
/// @}
/// \name Capacity
/// @{
///
/// \brief returns the number of elements in the array
/// \returns the number of elements in the array
[[nodiscard]] constexpr size_t size() const { return ElemV; }
///
/// \brief returns **true** when the array is empty
/// \return \f$ElemV == 0\f$
[[nodiscard]] constexpr bool_t empty() const { return ElemV == 0; }
/// @}
/// \name Comparison Operators
/// @{
///
/// \brief
friend constexpr bool_t operator==(const array& lhs, const array& rhs)
{ return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> bool_t // Lambda Declaration, Creates Indices at Compile Time
{ return ((lhs[i] == rhs[i]) && ...); }(make_index_sequence<ElemV>{}); } // Lambda Implementation,
friend constexpr bool_t operator!=(const array& lhs, const array& rhs)
{ return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> bool_t
{ return ((lhs[i] != rhs[i]) || ...); }(make_index_sequence<ElemV>{}); }
/// @}
};
}
#endif // FENNEC_CONTAINERS_ARRAY_H

View File

@ -0,0 +1,41 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file dynarray.h
/// \brief fennec::array definition & implementation
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_CONTAINERS_DYNARRAY_H
#define FENNEC_CONTAINERS_DYNARRAY_H
namespace fennec
{
}
#endif // FENNEC_CONTAINERS_DYNARRAY_H

View File

@ -0,0 +1,48 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file engine.h
/// \brief fennec::engine definition
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
///
/// \mainpage fennec
/// \anchor fennec
///
/// \include{doc} README.md
///
///
/// \section Libraries
///
/// \subpage page_fennec_math
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
#ifndef FENNEC_CORE_ENGINE_H
#define FENNEC_CORE_ENGINE_H
#endif // FENNEC_CORE_ENGINE_H

View File

@ -0,0 +1,65 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file conditional_types.h
/// \brief metaprogramming to conditionally set a type
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef CONDITIONAL_TYPES_H
#define CONDITIONAL_TYPES_H
#include <fennec/lang/type_transforms.h>
#include <fennec/lang/types.h>
namespace fennec
{
// fennec::conditional =================================================================================================
///
///
/// \brief select between two types based on a condition
///
/// \details
/// \tparam B the value of the condition
/// \tparam T type to use when \f$B == true\f$
/// \tparam F type to use when \f$B == false\f$
template<bool_t B, typename T, typename F> struct conditional;
/// \brief Shorthand for ```typename conditional<ConditionV, TrueT, FalseT>::type```
template<bool_t B, typename T, typename F> using conditional_t = typename conditional<B, T, F>::type;
/// \internal specialization of fennec::conditional for \c true case
template<typename T, typename F> struct conditional<true, T, F> : type_transform<T>{};
/// \internal specialization of fennec::conditional for \c false case
template<typename T, typename F> struct conditional<false, T, F> : type_transform<F>{};
}
#endif //CONDITIONAL_TYPES_H

View File

@ -0,0 +1,78 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file constants.h
/// \brief metaprogramming constants
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_CONSTANTS_H
#define FENNEC_LANG_CONSTANTS_H
#include <fennec/lang/types.h>
namespace fennec
{
///
/// \brief metaprogramming integral constant
///
/// \details
/// \tparam T type of the constant
/// \tparam V value of the constant
template<typename T, T V> struct integral_constant
{
///
/// \brief value of the constant
inline static constexpr T value = V;
///
///
/// \brief cast operator to allow for braced initialization
/// \returns the value of the constant
constexpr operator T() const noexcept { return V; }
};
///
///
/// \brief metaprogramming boolean constant
///
/// \details
/// \tparam V value of the constant
template<bool_t V> struct bool_constant : integral_constant<bool_t, V> {};
///
///
/// \brief metaprogramming true constant
struct true_type : bool_constant<true> {};
///
///
/// \brief metaprogramming false constant
struct false_type : bool_constant<false> {};
}
#endif // FENNEC_LANG_CONSTANTS_H

View File

@ -0,0 +1,70 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
/// \file __type_traits.h
/// \internal
#ifndef FENNEC_LANG_DETAIL_TYPE_TRAITS_H
#define FENNEC_LANG_DETAIL_TYPE_TRAITS_H
#include <fennec/lang/constants.h>
#include <fennec/lang/type_traits.h>
#include <fennec/lang/float.h>
namespace fennec
{
namespace detail
{
template<typename> struct __is_void_helper : false_type {};
template<> struct __is_void_helper<void> : true_type {};
template<typename> struct __is_bool_helper : false_type {};
template<> struct __is_bool_helper<bool_t> : true_type {};
template<typename> struct __is_integral_helper : false_type {};
template<> struct __is_integral_helper<bool_t> : true_type {};
template<> struct __is_integral_helper<char_t> : true_type {};
template<> struct __is_integral_helper<char8_t> : true_type {};
template<> struct __is_integral_helper<char16_t> : true_type {};
template<> struct __is_integral_helper<char32_t> : true_type {};
template<> struct __is_integral_helper<schar_t> : true_type {};
template<> struct __is_integral_helper<uchar_t> : true_type {};
template<> struct __is_integral_helper<wchar_t> : true_type {};
template<> struct __is_integral_helper<short_t> : true_type {};
template<> struct __is_integral_helper<ushort_t> : true_type {};
template<> struct __is_integral_helper<int_t> : true_type {};
template<> struct __is_integral_helper<uint_t> : true_type {};
template<> struct __is_integral_helper<long_t> : true_type {};
template<> struct __is_integral_helper<ulong_t> : true_type {};
template<> struct __is_integral_helper<llong_t> : true_type {};
template<> struct __is_integral_helper<ullong_t> : true_type {};
template<typename TypeT> struct __is_signed_helper : bool_constant<TypeT(-1) < TypeT(0)> {};
template<typename TypeT> struct __is_unsigned_helper : bool_constant<TypeT(-1) >= TypeT(0)> {};
template<typename> struct __is_floating_point_helper : false_type {};
template<> struct __is_floating_point_helper<float_t> : true_type {};
template<> struct __is_floating_point_helper<double_t> : true_type {};
}
}
#endif // FENNEC_LANG_DETAIL_TYPE_TRAITS_H

View File

@ -0,0 +1,82 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file float.h
/// \brief metaprogramming floating point type info
///
///
/// \details this file is automatically generated for the current build environment
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#include <fennec/memory/bits.h>
#define FLT_HAS_INFINITY 1
#define FLT_HAS_QUIET_NAN 1
#define FLT_HAS_SIGNALING_NAN 1
#define FLT_HAS_DENORM 1
#define FLT_HAS_DENORM_LOSS 0
#define FLT_ROUNDS 1
#define FLT_IS_IEC559 1
#define FLT_MANT_DIG 24
#define FLT_DIG 6
#define FLT_DECIMAL_DIG 9
#define FLT_RADIX 2
#define FLT_MIN_EXP -125
#define FLT_MAX_EXP 128
#define FLT_MIN_10_EXP -37
#define FLT_MAX_10_EXP 38
#define FLT_TRAPS 0
#define FLT_TINYNESS_BEFORE 0
#define FLT_MIN fennec::bit_cast<float>(0x800000)
#define FLT_MAX fennec::bit_cast<float>(0x7f7fffff)
#define FLT_EPSILON fennec::bit_cast<float>(0x34000000)
#define FLT_INF fennec::bit_cast<float>(0x7f800000)
#define FLT_QUIET_NAN fennec::bit_cast<float>(0x7fc00000)
#define FLT_SIGNALING_NAN fennec::bit_cast<float>(0x7fa00000)
#define FLT_DENORM_MIN fennec::bit_cast<float>(0x1)
#define FLT_ROUND_ERR fennec::bit_cast<float>(0x3f000000)
#define DBL_HAS_INFINITY 1
#define DBL_HAS_QUIET_NAN 1
#define DBL_HAS_SIGNALING_NAN 1
#define DBL_HAS_DENORM 1
#define DBL_HAS_DENORM_LOSS 0
#define DBL_ROUNDS 1
#define DBL_IS_IEC559 1
#define DBL_MANT_DIG 53
#define DBL_DIG 15
#define DBL_DECIMAL_DIG 17
#define DBL_RADIX 2
#define DBL_MIN_EXP -1021
#define DBL_MAX_EXP 1024
#define DBL_MIN_10_EXP -307
#define DBL_MAX_10_EXP 308
#define DBL_TRAPS 0
#define DBL_TINYNESS_BEFORE 0
#define DBL_MIN fennec::bit_cast<double>(0x10000000000000l)
#define DBL_MAX fennec::bit_cast<double>(0x7fefffffffffffffl)
#define DBL_EPSILON fennec::bit_cast<double>(0x3cb0000000000000l)
#define DBL_INF fennec::bit_cast<double>(0x7ff0000000000000l)
#define DBL_QUIET_NAN fennec::bit_cast<double>(0x7ff8000000000000l)
#define DBL_SIGNALING_NAN fennec::bit_cast<double>(0x7ff4000000000000l)
#define DBL_DENORM_MIN fennec::bit_cast<double>(0x1l)
#define DBL_ROUND_ERR fennec::bit_cast<double>(0x3fe0000000000000l)

View File

@ -0,0 +1,27 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_INTRINSICS_H
#define FENNEC_LANG_INTRINSICS_H
# if defined(__has_builtin)
# define FENNEC_HAS_BUILTIN_BITCAST __has_builtin(__builtin_bit_cast)
# endif
#endif // FENNEC_LANG_INTRINSICS_H

View File

@ -0,0 +1,154 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_LANG_LIMITS_H
#define FENNEC_LANG_LIMITS_H
#include <cmath>
#include <fennec/lang/types.h>
#include <fennec/lang/type_traits.h>
namespace fennec
{
enum float_round_style
{
round_indeterminate = -1
, round_toward_zero = 0
, round_to_nearest = 1
, round_toward_infinity = 2
, round_toward_neg_infinity = 3
};
template<typename TypeT> struct numeric_limits
{
static constexpr bool is_specialized = false;
static constexpr bool is_signed = false;
static constexpr bool is_integer = false;
static constexpr bool is_exact = false;
static constexpr bool has_infinity = false;
static constexpr bool has_quiet_nan = false;
static constexpr bool has_signaling_nan = false;
static constexpr bool has_denorm = false;
static constexpr bool has_denorm_loss = false;
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = false;
static constexpr bool is_modulo = false;
static constexpr bool tinyness_before = false;
static constexpr bool traps = false;
static constexpr int digits = 0;
static constexpr int digits10 = 0;
static constexpr int max_digits10 = 0;
static constexpr int radix = 0;
static constexpr int min_exponent = 0;
static constexpr int min_exponent10 = 0;
static constexpr int max_exponent = 0;
static constexpr int max_exponent10 = 0;
static constexpr float_round_style rounding_style = round_indeterminate;
static constexpr TypeT min() { return TypeT(); }
static constexpr TypeT max() { return TypeT(); }
static constexpr TypeT lowest() { return TypeT(); }
static constexpr TypeT epsilon() { return TypeT(); }
static constexpr TypeT round_error() { return TypeT(); }
static constexpr TypeT infinity() { return TypeT(); }
static constexpr TypeT quiet_NaN() { return TypeT(); }
static constexpr TypeT signaling_NaN() { return TypeT(); }
static constexpr TypeT denorm_min() { return TypeT(); }
};
template<> struct numeric_limits<float>
{
static constexpr bool is_specialized = true;
static constexpr bool is_signed = true;
static constexpr bool is_integer = false;
static constexpr bool is_exact = false;
static constexpr bool has_infinity = FLT_HAS_INFINITY;
static constexpr bool has_quiet_nan = FLT_HAS_QUIET_NAN;
static constexpr bool has_signaling_nan = FLT_HAS_SIGNALING_NAN;
static constexpr bool has_denorm = FLT_HAS_DENORM;
static constexpr bool has_denorm_loss = FLT_HAS_DENORM_LOSS;
static constexpr bool is_iec559 = FLT_IS_IEC559;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
static constexpr bool tinyness_before = FLT_TINYNESS_BEFORE;
static constexpr bool traps = FLT_TRAPS;
static constexpr int digits = FLT_MANT_DIG;
static constexpr int digits10 = FLT_DIG;
static constexpr int max_digits10 = FLT_DECIMAL_DIG;
static constexpr int radix = FLT_RADIX;
static constexpr int min_exponent = FLT_MIN_EXP;
static constexpr int min_exponent10 = FLT_MIN_10_EXP;
static constexpr int max_exponent = FLT_MAX_EXP;
static constexpr int max_exponent10 = FLT_MAX_10_EXP;
static constexpr double min() { return FLT_MIN; }
static constexpr double max() { return FLT_MAX; }
static constexpr double lowest() { return -FLT_MAX; }
static constexpr double epsilon() { return FLT_EPSILON; }
static constexpr double round_error() { return FLT_ROUND_ERR; }
static constexpr double infinity() { return FLT_INF; }
static constexpr double quiet_NaN() { return FLT_QUIET_NAN; }
static constexpr double signaling_NaN() { return FLT_SIGNALING_NAN; }
static constexpr double denorm_min() { return FLT_DENORM_MIN; }
};
template<> struct numeric_limits<double>
{
static constexpr bool is_specialized = true;
static constexpr bool is_signed = true;
static constexpr bool is_integer = false;
static constexpr bool is_exact = false;
static constexpr bool has_infinity = DBL_HAS_INFINITY;
static constexpr bool has_quiet_nan = DBL_HAS_QUIET_NAN;
static constexpr bool has_signaling_nan = DBL_HAS_SIGNALING_NAN;
static constexpr bool has_denorm = DBL_HAS_DENORM;
static constexpr bool has_denorm_loss = DBL_HAS_DENORM_LOSS;
static constexpr bool is_iec559 = DBL_IS_IEC559;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
static constexpr bool tinyness_before = DBL_TINYNESS_BEFORE;
static constexpr bool traps = DBL_TRAPS;
static constexpr int digits = DBL_MANT_DIG;
static constexpr int digits10 = DBL_DIG;
static constexpr int max_digits10 = DBL_DECIMAL_DIG;
static constexpr int radix = DBL_RADIX;
static constexpr int min_exponent = DBL_MIN_EXP;
static constexpr int min_exponent10 = DBL_MIN_10_EXP;
static constexpr int max_exponent = DBL_MAX_EXP;
static constexpr int max_exponent10 = DBL_MAX_10_EXP;
static constexpr double min() { return DBL_MIN; }
static constexpr double max() { return DBL_MAX; }
static constexpr double lowest() { return -DBL_MAX; }
static constexpr double epsilon() { return DBL_EPSILON; }
static constexpr double round_error() { return DBL_ROUND_ERR; }
static constexpr double infinity() { return DBL_INF; }
static constexpr double quiet_NaN() { return DBL_QUIET_NAN; }
static constexpr double signaling_NaN() { return DBL_SIGNALING_NAN; }
static constexpr double denorm_min() { return DBL_DENORM_MIN; }
};
}
#endif // FENNEC_LANG_LIMITS_H

View File

@ -0,0 +1,225 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file sequences.h
/// \brief metaprogramming sequences
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_SEQUENCES_H
#define FENNEC_LANG_SEQUENCES_H
#include <fennec/lang/type_traits.h>
namespace fennec
{
// fennec::sequence ====================================================================================================
///
///
/// \brief metaprogramming sequence
///
/// \details
/// \tparam ValueT type of the values
/// \tparam ValuesV sequence values
///
template<typename ValueT, ValueT...ValuesV> struct sequence
{
///
/// \brief type of the sequence
using value_type = ValueT;
///
/// \brief self-referential type
using type = sequence;
///
///
/// \brief returns the number of elements
///
/// \return number of elements in the array
inline static constexpr size_t size() noexcept { return sizeof...(ValuesV); }
};
// fennec::integer_sequence ============================================================================================
///
///
/// \brief metaprogramming integral sequence
///
/// \details
/// \tparam T type of the values, must satisfy ```fennec::is_integral<T>```
/// \tparam Values sequence values
///
template<typename T, T...Values> requires(is_integral_v<T>)
struct integer_sequence : sequence<T, Values...>
{
///
/// \brief type of the sequence
using value_type = T;
///
/// \brief self-referential type
using type = integer_sequence;
///
///
/// \brief returns the number of elements
///
/// \return number of elements in the array
inline static constexpr size_t size() noexcept { return sizeof...(Values); }
};
///
///
/// \brief generate a fennec::integer_sequence \f$\left[\,0\,\ldots\,N\,\right)\f$
///
/// \details
/// \tparam T type of the values, must satisfy ```fennec::is_integral<T>```
/// \tparam N size of the sequence to generate
///
template<typename T, size_t N> struct make_integer_sequence;
///
/// \brief shorthand for ```typename make_integer_sequence<T, N>::type```
template<typename T, size_t N> using make_integer_sequence_t = typename make_integer_sequence<T, N>::type;
// fennec::index_sequence ==============================================================================================
///
///
/// \brief metaprogramming integral sequence
///
/// \details
/// \tparam Indices sequence values
///
template<size_t...Indices> struct index_sequence : integer_sequence<size_t, Indices...>
{
///
/// \brief type of the sequence
using value_type = size_t;
///
/// \brief self-referential type
using type = index_sequence;
///
///
/// \brief returns the number of elements
///
/// \return number of elements in the array
inline static constexpr size_t size() noexcept { return sizeof...(Indices); }
};
///
///
/// \brief generate a fennec::index_sequence \f$\left[\,0\,\ldots\,N\,\right)\f$
///
/// \details
/// \tparam T type of the values, must satisfy ```fennec::is_integral<T>```
/// \tparam N size of the sequence to generate
///
template<size_t N> struct make_index_sequence;
///
/// \brief shorthand for ```typename make_index_sequence<N>::type```
template<size_t N> using make_index_sequence_t = typename make_index_sequence<N>::type;
// fennec::concat_sequence =============================================================================================
///
///
/// \brief concatenate two sequences
///
/// \details
/// \tparam SequenceT0 lhs
/// \tparam SequenceT1 rhs
template<typename SequenceT0, typename SequenceT1> struct concat_sequence;
///
/// \brief shorthand for ```typename concat_sequence<SequenceT0, SequenceT1>::type```
template<typename SequenceT0, typename SequenceT1> using concat_sequence_t
= typename concat_sequence<SequenceT0, SequenceT1>::type;
///
///
/// \brief specialization to concatenate two integer sequences
///
/// \details
/// \tparam T integral type
/// \tparam SequenceT0 lhs
/// \tparam SequenceT1 rhs
template<typename T, T...SequenceV0, T...SequenceV1>
struct concat_sequence<integer_sequence<T, SequenceV0...>, integer_sequence<T, SequenceV1...>>
: integer_sequence<T, SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
///
///
/// \brief specialization to concatenate two index sequences
///
/// \details
/// \tparam SequenceT0 lhs
/// \tparam SequenceT1 rhs
template<size_t...SequenceV0, size_t...SequenceV1>
struct concat_sequence<index_sequence<SequenceV0...>, index_sequence<SequenceV1...>>
: index_sequence<SequenceV0..., (sizeof...(SequenceV0) + SequenceV1)...>{};
// Internal ============================================================================================================
/// \internal Implementation for Generating an \ref integer_sequence
template<typename T, size_t N> struct make_integer_sequence : concat_sequence_t<make_integer_sequence_t<T, N / 2>, make_integer_sequence_t<T, N - N / 2>>{};
/// \internal Base Case of \f$N=0\f$
template<typename T> struct make_integer_sequence<T, 0> : integer_sequence<T> {};
/// \internal Base Case of \f$N=1\f$
template<typename T> struct make_integer_sequence<T, 1> : integer_sequence<T, 0>{};
/// \internal Implementation for Generating an \ref integer_sequence
template<size_t N> struct make_index_sequence : concat_sequence_t<make_index_sequence_t<N / 2>, make_index_sequence_t<N - N / 2>>{};
/// \internal Base Case of \f$N=0\f$
template<> struct make_index_sequence<0> : index_sequence<> {};
/// \internal Base Case of \f$N=1\f$
template<> struct make_index_sequence<1> : index_sequence<0>{};
}
#endif // FENNEC_LANG_SEQUENCES_H

View File

@ -0,0 +1,195 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file type_traits.h
/// \brief get info about types at compile-time
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_TYPE_TRAITS_H
#define FENNEC_LANG_TYPE_TRAITS_H
#include <fennec/lang/type_transforms.h>
#include <fennec/lang/detail/__type_traits.h>
namespace fennec
{
// fennec::is_void =====================================================================================================
///
///
/// \brief check if \p T is of type void
///
/// \details
/// \tparam T type to check
template<typename T> struct is_void
: detail::__is_void_helper<remove_cvr_t<T>>{};
///
///
/// \brief shorthand for ```is_void<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_void_v
= is_void<T>::value;
// fennec::is_bool =====================================================================================================
///
///
/// \brief check if \p T is of type bool
///
/// \details
/// \tparam T type to check
template<typename T> struct is_bool
: detail::__is_bool_helper<remove_cvr_t<T>>{};
///
///
/// \brief shorthand for ```is_bool<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_bool_v
= is_bool<T>::value;
// Integral Types ======================================================================================================
///
///
/// \brief check if \p T is of an integral
///
/// \details
/// \tparam T type to check
template<typename T> struct is_integral
: detail::__is_integral_helper<remove_cvr_t<T>> {};
///
///
/// \brief shorthand for ```is_integral<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_integral_v
= is_integral<T>::value;
///
///
/// \brief check if \p T is of a signed integral
///
/// \details
/// \tparam T type to check
template<typename T> struct is_signed
: detail::__is_signed_helper<remove_cvr_t<T>> {};
///
///
/// \brief shorthand for ```is_signed<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_signed_v
= is_signed<T>::value;
///
///
/// \brief check if \p T is of an unsigned integral
///
/// \details
/// \tparam T type to check
template<typename T> struct is_unsigned
: detail::__is_unsigned_helper<remove_cvr_t<T>> {};
///
///
/// \brief shorthand for ```is_unsigned<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_unsigned_v
= is_unsigned<T>::value;
// Floating Point Types ================================================================================================
///
///
/// \brief check if \p T is of a floating point type
///
/// \details
/// \tparam T type to check
template<typename T> struct is_floating_point
: detail::__is_floating_point_helper<remove_cvr_t<T>>{};
///
///
/// \brief shorthand for ```is_floating_point<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_floating_point_v
= is_floating_point<T> {};
// Arithmetic Types ====================================================================================================
///
///
/// \brief check if \p T is an arithmetic type
///
/// \details
/// \tparam T type to check
template<typename T> struct is_arithmetic
: bool_constant<is_integral_v<T> or is_floating_point_v<T>>{};
///
///
/// \brief shorthand for ```is_arithmetic<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool_t is_arithmetic_v
= is_arithmetic<T>::value;
// fennec::is_same =====================================================================================================
///
///
/// \brief check if
///
/// \details
/// \tparam T type to check
template<typename T0, typename T1> struct is_same
: false_type {};
template<typename T> struct is_same<T, T>
: true_type {};
///
///
/// \brief shorthand for ```is_same<T0, T1>::value```
/// \tparam T type to check
template<typename T0, typename T1> constexpr bool_t is_same_v
= is_same<T0, T1> {};
}
#endif // FENNEC_LANG_TYPE_TRAITS_H

View File

@ -0,0 +1,276 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General License for more details.
//
// You should have received a copy of the GNU General License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file type_transforms.h
/// \brief modify types at compile time
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_TYPE_TRANSFORMS_H
#define FENNEC_LANG_TYPE_TRANSFORMS_H
namespace fennec
{
// fennec::type_transform ==============================================================================================
///
/// \struct fennec::type_transform
/// \brief Base Class for Type Transformations
///
/// \details resembles a transformation from one type to T, the result is stored in the typedef type_transform::type
/// \tparam T Resultant Type
template<typename T> struct type_transform {
///
/// \typedef type_transform::type
/// \brief the type to transform into
using type = T;
};
// Pointer Conversions =================================================================================================
///
/// \struct fennec::add_pointer
/// \brief adds a pointer level to \p T
///
/// \details adds a pointer to the provided type such that ```T``` becomes ```T*```
/// \tparam T Resultant Type
template<typename T> struct add_pointer : type_transform<T*>{};
///
/// \typedef fennec::add_pointer_t
/// \brief shorthand for ```typename add_pointer<T>::type```
template<typename T> using add_pointer_t = typename add_pointer<T>::type;
///
/// \struct fennec::remove_pointer
/// \brief removes a pointer level from \p T
///
/// \details removes a pointer from the provided type such that ```T*``` becomes ```T```
/// \tparam T Resultant Type
template<typename T> struct remove_pointer : type_transform<T> {};
/// \internal specialization for T*
template<typename T> struct remove_pointer<T*> : type_transform<T> {};
///
/// \typedef fennec::remove_pointer_t
/// \brief shorthand for ```typename remove_pointer<T>::type```
template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;
// Reference Conversions ===============================================================================================
///
/// \struct fennec::add_reference
/// \brief add a reference to \p T
///
/// \details adds a pointer to the provided type such that ```T``` becomes ```T&```
/// \tparam T Resultant Type
template<typename T> struct add_reference : type_transform<T&> {};
///
/// \typedef fennec::add_reference_t
/// \brief shorthand for ```typename add_reference<T>::type```
template<typename T> using add_reference_t = typename add_reference<T>::type;
///
/// \struct fennec::remove_reference
/// \brief remove a reference from \p T
///
/// \details removes references from the provided type such that ```T&``` and ```T&&``` become ```T```
/// \tparam T Reference Type
template<typename T> struct remove_reference : type_transform<T> {};
/// \internal specialization for ```T&```
template<typename T> struct remove_reference<T&> : type_transform<T> {};
/// \internal specialization for ```T&&```
template<typename T> struct remove_reference<T&&> : type_transform<T> {};
///
/// \typedef fennec::remove_reference_t
/// \brief shorthand for ```typename remove_reference<T>::type```
template<typename T> using remove_reference_t = typename remove_reference<T>::type;
// Const & Volatile Conversions ========================================================================================
///
/// \struct fennec::add_const
/// \brief add the const qualifier to the provided type \p T
///
/// \details adds const qualification to the provided type such that ```T``` becomes ```const T```
/// \tparam T Reference Type
template<typename T> struct add_const : type_transform<const T> {};
///
/// \typedef fennec::add_const_t
/// \brief shorthand for ```typename add_const<T>::type```
template<typename T> using add_const_t = typename add_const<T>::type;
/// \internal specialization for const types
template<typename T> struct add_const<const T> : type_transform<const T> {};
///
/// \struct fennec::remove_const
/// \brief remove the const qualifier from the provided type \p T
///
/// \details removes const qualification from the provided type such that ```const T``` becomes ```T```
/// \tparam T Reference Type
template<typename T> struct remove_const : type_transform<T> {};
///
/// \typedef fennec::remove_const_t
/// \brief shorthand for ```typename remove_const<T>::type```
template<typename T> using remove_const_t = typename remove_const<T>::type;
/// \internal specialization for const types
template<typename T> struct remove_const<const T> : type_transform<T> {};
///
/// \struct fennec::add_volatile
/// \brief add the volatile qualifier to the provided type \p T
///
/// \details removes references from the provided type such that ```T``` becomes ```volatile T```
/// \tparam T Reference Type
template<typename T> struct add_volatile : type_transform<volatile T> {};
///
/// \typedef fennec::add_volatile_t
/// \brief shorthand for ```typename add_volatile<T>::type```
template<typename T> using add_volatile_t = typename add_volatile<T>::type;
/// \internal specialization for volatile types
template<typename T> struct add_volatile<volatile T> : type_transform<volatile T> {};
///
/// \struct fennec::remove_volatile
/// \brief remove the volatile qualifier from the provided type \p T
///
/// \details removes references from the provided type such that ```volatile T``` becomes ```T```
/// \tparam T Reference Type
template<typename T> struct remove_volatile : type_transform<T> {};
///
/// \typedef fennec::remove_volatile_t
/// \brief shorthand for ```typename remove_volatile<T>::type```
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;
/// \internal specialization for volatile types
template<typename T> struct remove_volatile<volatile T> : type_transform<T> {};
///
/// \struct fennec::add_cv
/// \brief remove the volatile qualifier from the provided type \p T
///
/// \details removes references from the provided type such that ```T```, ```const T```, and ```volatile T``` become
/// ```const volatile T```
/// \tparam T Reference Type
template<typename T> struct add_cv : type_transform<const volatile T> {};
///
/// \typedef fennec::add_cv_t
/// \brief shorthand for ```typename add_cv<T>::type```
template<typename T> using add_cv_t = typename add_cv<T>::type;
/// \internal specialization for const types
template<typename T> struct add_cv<const T> : type_transform<const volatile T> {};
/// \internal specialization for volatile types
template<typename T> struct add_cv<volatile T> : type_transform<const volatile T> {};
/// \internal specialization for const volatile types
template<typename T> struct add_cv<const volatile T> : type_transform<const volatile T> {};
///
///
/// \brief remove the const and volatile qualifiers from the provided type \p T
///
/// \details removes const and volatile from the provided type such that ```const T```, ```volatile T```, and
/// ```const volatile T``` become ```T```
/// \tparam T Reference Type
template<typename T> struct remove_cv : type_transform<T> {};
/// \internal specialization for const types
template<typename T> struct remove_cv<const T> : type_transform<T> {};
/// \internal specialization for volatile types
template<typename T> struct remove_cv<volatile T> : type_transform<T> {};
/// \internal specialization for const volatile types
template<typename T> struct remove_cv<const volatile T> : type_transform<T> {};
///
/// \brief shorthand for ```typename remove_cv<T>::type```
template<typename T> using remove_cv_t = typename remove_cv<T>::type;
///
///
/// \brief add a reference and the const volatile qualifiers from the provided type \p T
///
/// \details adds references and const volatile qualifiers to the provided type.
/// \tparam T Reference Type
template<typename T> struct add_cvr : type_transform<add_reference_t<add_cv_t<T>>> {};
///
/// \brief shorthand for ```typename add_cvr<T>::type```
template<typename T> using add_cvr_t = typename add_cvr<T>::type;
///
///
/// \brief removes references as well as the const and volatile qualifiers from the provided type \p T
///
/// \details removes const and volatile from the provided type such that
/// \tparam T Reference Type
template<typename T> struct remove_cvr : type_transform<remove_cv_t<remove_reference_t<T>>> {};
///
/// \brief shorthand for ```typename remove_cvr<T>::type```
template<typename T> using remove_cvr_t = typename remove_cvr<T>::type;
}
#endif // FENNEC_LANG_TYPE_TRANSFORMS_H

204
include/fennec/lang/types.h Normal file
View File

@ -0,0 +1,204 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file types.h
/// \brief basic types of the c++ language
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_LANG_TYPES_H
#define FENNEC_LANG_TYPES_H
#include <cstdint>
namespace fennec
{
// Basic Types =========================================================================================================
///
/// \name Basic Types
/// @{
///
/// \brief A conditional type
using bool_t = bool;
///
/// \brief A type capable of holding an ascii value
using char_t = char;
///
/// \brief A type with the size of a char, capable of holding a signed 8-bit integer
using schar_t = signed char;
///
/// \brief A type with the size of a char, capable of holding an unsigned 8-bit integer
using uchar_t = unsigned char;
///
/// \brief A short type, capable of holding signed 16-bit integer
using short_t = signed short;
///
/// \brief A short type, capable of holding an unsigned signed 16-bit integer
using ushort_t = unsigned short;
///
/// \brief A signed integer type, size varies by implementation, but typically 32-bit
using int_t = signed int;
///
/// \brief An unsigned integer type, size varies by implementation, but typically 32-bit
using uint_t = unsigned int;
///
/// \brief A signed integer type, with a size of at least 32-bits
using long_t = signed long;
///
/// \brief An unsigned integer type, with a size of at least 32-bits
using ulong_t = unsigned long;
///
/// \brief A signed integer type, with a size of 64-bits
using llong_t = signed long long;
///
/// \brief An unsigned integer type, with a size of 64-bits
using ullong_t = unsigned long long;
///
/// \brief A single-precision floating-point type, with a size of 32-bits
using float_t = float;
///
/// \brief A double-point type, with a size of 64-bits
using double_t = double;
/// @}
// Sized Arithmetic Types ==============================================================================================
///
/// \name Sized Integer Types
/// @{
///
/// \brief Signed 8-bit integer
using int8_t = schar_t;
///
/// \brief Signed 16-bit integer
using int16_t = short_t;
///
/// \brief Signed 32-bit integer
using int32_t = long_t;
///
/// \brief Signed signed 64-bit integer
using int64_t = llong_t;
/// @}
///
/// \name Sized Unsigned Integer Types
/// @{
///
/// \brief Unsigned 8-bit integer
using uint8_t = uchar_t;
///
/// \brief Unsigned 16-bit integer
using uint16_t = ushort_t;
///
/// \brief Unsigned 32-bit integer
using uint32_t = ulong_t;
///
/// \brief Unsigned 64-bit integer
using uint64_t = ullong_t;
/// @}
///
/// \name Sized Floating-Point Types
/// @{
///
/// \brief A single-precision floating-point scalar
using float32_t = float_t;
///
/// \brief A double-precision floating-point scalar
using float64_t = double_t;
/// @}
///
/// \name Special Types
/// @{
///
/// \brief Null Pointer Type
using nullptr_t = decltype(nullptr);
///
/// \brief Signed Integer Capable of Holding a Pointer to void
using intptr_t = intptr_t;
///
/// \brief Unsigned Integer Capable of Holding a Pointer to void
using uintptr_t = uintptr_t;
///
/// \brief Maximum Width Signed Integer Type
using intmax_t = __INTMAX_TYPE__;
///
/// \brief Maximum Width Unsigned Integer Type
using uintmax_t = __UINTMAX_TYPE__;
///
/// \brief Unsigned Integer Type Returned By `sizeof`, `sizeof...`, and `alignof`
using size_t = __SIZE_TYPE__;
///
/// \brief Signed Integer Type Returned by the Subtraction of two Pointers
using ptrdiff_t = __PTRDIFF_TYPE__;
/// @}
}
#endif // FENNEC_LANG_TYPES_H

View File

@ -0,0 +1,81 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file utility.h
/// \brief common utility functions related to the c++ language
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef UTILITY_H
#define UTILITY_H
#include <fennec/lang/type_transforms.h>
namespace fennec
{
///
///
/// \details
/// \tparam T base type of the object
/// \param x reference to the object
/// \returns
template<typename T> constexpr T&& forward(remove_reference_t<T>& x) noexcept { return x; }
///
///
/// \brief forwards reference types to extend their lifetime
///
/// \details
/// \tparam T base type of the object
/// \param x reference to the object
/// \returns
template<typename T> constexpr T&& forward(remove_reference_t<T>&& x) noexcept { return x; }
///
///
/// \brief produces an x-value type to indicate \p x may be "moved"
///
/// \details
/// \tparam T base type of the object
/// \param x object to be moved
/// \returns `static_cast<remove_reference_t<T>&&>(x)`
template<typename T> constexpr remove_reference_t<T>&& move(T&& x) noexcept { return static_cast<remove_reference_t<T>&&>(x); }
///
///
/// \brief produces an r-value type to indicate \p x may be "copied"
///
/// \details
/// \tparam T base type of the object
/// \param x object to be copied
/// \returns const r-value
template<typename T> constexpr const remove_reference_t<T>& copy(T&& x) noexcept { return x; }
}
#endif //UTILITY_H

1233
include/fennec/math/common.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
/// \file __fwd.h
/// \internal
#ifndef FWD_H
#define FWD_H
#include <fennec/math/detail/__types.h>
namespace fennec
{
template<typename ScalarT, size_t...IndicesV> struct vector;
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> struct matrix;
template<typename ScalarT, size_t SizeV> using vec = decltype(detail::__gen_vector<vector, ScalarT>(make_index_sequence<SizeV>{}));
template<typename ScalarT, size_t RowsV, size_t ColsV> using mat = decltype(detail::__gen_matrix<matrix, ScalarT, RowsV>(make_index_sequence<ColsV>{}));
}
#endif //FWD_H

View File

@ -0,0 +1,43 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
/// \file __types.h
/// \internal
#ifndef FENNEC_MATH_DETAIL_TYPES_H
#define FENNEC_MATH_DETAIL_TYPES_H
#include <fennec/lang/sequences.h>
namespace fennec
{
namespace detail
{
/// \internal
template<template<typename, size_t...> typename VectorT, typename ScalarT, size_t...IndicesV> VectorT<ScalarT, IndicesV...> __gen_vector(index_sequence<IndicesV...>);
/// \internal
template<template<typename, size_t...> typename MatrixT, typename ScalarT, size_t RowsV, size_t...IndicesV> MatrixT<ScalarT, RowsV, IndicesV...> __gen_matrix(index_sequence<IndicesV...>);
}
}
#endif // FENNEC_MATH_DETAIL_TYPES_H

View File

@ -0,0 +1,52 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
/// \file __vector_traits.h
/// \internal
#ifndef FENNEC_MATH_DETAIL_VECTOR_TRAITS_H
#define FENNEC_MATH_DETAIL_VECTOR_TRAITS_H
#include <fennec/math/detail/__fwd.h>
#include <fennec/lang/type_traits.h>
#include <fennec/math/swizzle.h>
namespace fennec
{
namespace detail
{
template<typename> struct __is_vector_helper : false_type {};
template<typename ScalarT, size_t...IndicesV> struct __is_vector_helper<vector<ScalarT, IndicesV...>> : true_type {};
template<typename VectorT, typename DataT, typename ScalarT, size_t...IndicesV>
struct __is_vector_helper<swizzle<VectorT, DataT, ScalarT, IndicesV...>> : true_type {};
template<typename> struct __component_count_helper;
template<typename TypeT> requires(is_arithmetic_v<TypeT>) struct __component_count_helper<TypeT> : integral_constant<size_t, 1> {};
template<typename ScalarT, size_t...IndicesV> struct __component_count_helper<vector<ScalarT, IndicesV...>> : integral_constant<size_t, sizeof...(IndicesV)> {};
template<typename VectorT, typename DataT, typename ScalarT, size_t...IndicesV> struct __component_count_helper<swizzle<VectorT, DataT, ScalarT, IndicesV...>> : integral_constant<size_t, sizeof...(IndicesV)> {};
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV> struct __component_count_helper<matrix<ScalarT, RowsV, ColIndicesV...>> : integral_constant<size_t, RowsV * sizeof...(ColIndicesV)> {};
template<typename> struct __component_count_helper : integral_constant<size_t, 0> {};
}
}
#endif // FENNEC_MATH_DETAIL_VECTOR_TRAITS_H

View File

@ -0,0 +1,220 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file exponential.h
/// \brief \ref page_fennec_math_exponential
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_MATH_EXPONENTIAL_H
#define FENNEC_MATH_EXPONENTIAL_H
#include <cmath>
///
///
///
/// \page page_fennec_math_exponential Exponential
///
/// \brief The Exponential Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
///
///
/// \section Exponential Functions
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_curve_functions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::pow(fennec::genFType<>, fennec::genFType<>) "genFType pow(genFType, genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::pow(fennec::genFType<>, fennec::genFType<>)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::exp(fennec::genFType<>)"genFType exp(genFType)"
/// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::exp(fennec::genFType<>)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::exp2(fennec::genFType<>) "genFType exp2(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::exp2(fennec::genFType<>)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::log(fennec::genFType<>) "genFType log(genFType)"
/// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::log(fennec::genFType<>)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::log2(fennec::genFType<>) "genFType log2(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::log2(fennec::genFType<>)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::sqrt(fennec::genFType<>) "genFType sqrt(genFType)"
/// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::sqrt(fennec::genFType<>)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::inversesqrt(fennec::genFType<>) "genFType inversesqrt(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::inversesqrt(fennec::genFType<>)
///
/// </table>
///
///
///
namespace fennec
{
// pow -----------------------------------------------------------------------------------------------------------------
///
/// \fn fennec::pow(fennec::genType, fennec::genType)
/// \brief Returns \f$x\f$ raised to the \f$y\f$ power, i.e., \f$x^y\f$.
///
/// \returns \f$x\f$ raised to the \f$y\f$ power, i.e., \f$x^y\f$.<br><br>
/// \details Results are undefined if \f$x<0\f$. <br><br>Results are undefined if \f$x=0\f$ and \f${y}\le{0}\f$.<br><br>
///
/// \param x the base
/// \param y the exponent
template<typename genType>
constexpr genType pow(genType x, genType y)
{ return std::pow(x, y); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> pow(const vector<genType, i...> & x, const vector<genType, i...> & y)
{ return vector<genType, i...>(fennec::pow(x[i], y[i]) ...); }
// exp -----------------------------------------------------------------------------------------------------------------
///
/// \fn fennec::exp(fennec::genType)
/// \brief Returns the natural exponentiation of \f$x\f$, i.e., \f$e^x\f$
///
/// \returns the natural exponentiation of \f$x\f$, i.e., \f$e^x\f$.<br><br>
///
/// \param x the exponent
template<typename genType>
constexpr genType exp(genType x)
{ return std::exp(x); }
template<typename genType, size_t...i> constexpr vector<genType, i...> exp(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::exp(x[i]) ...); }
// exp2 ----------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns 2 raised to the \f$x\f$ power, i.e., \f$e^x\f$
///
/// \returns 2 raised to the \f$x\f$ power, i.e., \f$e^x\f$<br><br>
///
/// \param x the exponent
template<typename genType> constexpr genType exp2(genType x)
{ return std::exp2(x); }
template<typename genType, size_t...i> constexpr vector<genType, i...> exp2(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::exp2(x[i]) ...); }
// log -----------------------------------------------------------------------------------------------------------------
///
/// \fn fennec::log(fennec::genType)
/// \brief Returns the natural logarithm of \f$x\f$.
///
/// \returns the natural logarithm of \f$x\f$, i.e., returns the value \f$y\f$ which satisfies the equation \f$x=e^y\f$.<br><br>
/// \details Results are undefined if \f${x}\le{0}\f$.<br><br>
///
/// \param x the input value
template<typename genType> constexpr genType log(genType x)
{ return std::log(x); }
template<typename genType, size_t...i> constexpr genType log(const vector<genType, i...>& x)
{ return vector<genType, i...>(log(x[i]) ...); }
// log2 ----------------------------------------------------------------------------------------------------------------
///
/// \fn fennec::log2(fennec::genType)
/// \brief Returns the base 2 logarithm of \f$x\f$.
///
/// \returns the base 2 logarithm of \f$x\f$, i.e., returns the value \f$y\f$ which satisfies the equation
/// \f$x=2^y\f$. <br><br>
/// \details Results are undefined if \f${x}\le{0}\f$. <br><br>
///
/// \param x the input value
template<typename genType> constexpr genType log2(genType x)
{ return std::log2(x); }
template<typename genType, size_t...i> constexpr genType log2(const vector<genType, i...>& x)
{ return vector<genType, i...>(log2(x[i]) ...); }
// sqrt ----------------------------------------------------------------------------------------------------------------
///
/// \fn fennec::sqrt(fennec::genType)
/// \brief Returns \f$\sqrt{x}\f$.
///
/// \returns \f$\sqrt{x}\f$. <br><br>
/// \details Results are undefined if \f$x<0\f$<br><br>
///
/// \param x the input value
template<typename genType> constexpr genType sqrt(genType x)
{ return std::sqrt(x); }
template<typename genType, size_t...i> constexpr genType sqrt(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sqrt(x[i]) ...); }
// inversesqrt ---------------------------------------------------------------------------------------------------------
///
/// \fn fennec::inversesqrt(fennec::genType)
/// \brief Returns \f$\frac{1}{\sqrt{x}}\f$.
///
/// \returns \f$\frac{1}{\sqrt{x}}\f$.<br><br>
/// \details Results are undefined if \f$x<0\f$.<br><br>
///
/// \param x the input value
template<typename genType> constexpr genType inversesqrt(genType x)
{ return 1.0f / std::sqrt(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> inversesqrt(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::inversesqrt(x[i]) ...); }
}
#endif // FENNEC_MATH_EXPONENTIAL_H

View File

@ -0,0 +1,285 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file geometric.h
/// \brief \ref page_fennec_math_geometric
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_MATH_GEOMETRIC_H
#define FENNEC_MATH_GEOMETRIC_H
#include <fennec/math/vector.h>
#include <fennec/math/exponential.h>
///
///
///
/// \page page_fennec_math_geometric Geometric
///
/// \brief The Geometric Functions defined in the [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
///
///
/// \section Geometric Functions
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_geometric_functions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::dot(const genFType&, const genFType&) "float dot(genFType x, genFType y)" <br>
/// \ref fennec::dot(const genDType&, const genDType&) "double dot(genDType x, genDType x)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::dot(const genFType&, const genFType&)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::length2(const genFType&) "float length2(genFType x)" <br>
/// \ref fennec::length2(const genDType&) "double length2(genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::length2(const genFType&)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::length(const genFType&) "float length(genFType x)" <br>
/// \ref fennec::length(const genDType&) "double length(genDType x)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::length(const genFType&)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::distance(const genFType&, const genFType&) "float distance(genFType x, genFType y)" <br>
/// \ref fennec::distance(const genDType&, const genDType&) "double distance(genDType x, genDType x)"
/// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::distance(const genFType&, const genFType&)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::normalize(const genFType&) "float normalize(genFType x)" <br>
/// \ref fennec::normalize(const genDType&) "double normalize(genDType x)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::normalize(const genFType&)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::cross(const fennec::vec3&, const fennec::vec3&) "vec3 cross(vec3 x, vec3 y)" <br>
/// \ref fennec::cross(const fennec::dvec3&, const fennec::dvec3&) "dvec3 cross(dvec3 x, dvec3 x)"
/// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::cross(const fennec::vec3&, const fennec::vec3&)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::faceforward(const genFType&, const genFType&, const genFType&) "genFType faceforward(genFType N, genFType I, genFType Nref)" <br>
/// \ref fennec::faceforward(const genDType&, const genDType&, const genDType&) "genDType faceforward(genDType N, genDType I, genDType Nref)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::faceforward(const genFType&, const genFType&, const genFType&)
///
/// <tr><td width="50%" style="vertical-align: top" class="odd_c"> <br>
/// \ref fennec::reflect(const genFType&, const genFType&) "genFType reflect(genFType I, genFType N)" <br>
/// \ref fennec::reflect(const genDType&, const genDType&) "genDType reflect(genDType I, genDType N)"
/// <td width="50%" style="vertical-align: top" class="odd_c">
/// \copydoc fennec::reflect(const genFType&, const genFType&)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::refract(const genFType&, const genFType&, float) "genFType refract(genFType N, genFType I, float eta)" <br>
/// \ref fennec::refract(const genDType&, const genDType&, double) "genDType refract(genDType N, genDType I, double eta)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::refract(const genFType&, const genFType&, float)
///
/// </table>
///
///
///
namespace fennec
{
// dot -----------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_0 \cdot y_0 + \ldots\f$
///
/// \returns the dot product of \f$x\f$ and \f$y\f$, i.e., \f$x_0 \cdot y_0 + x_0 \cdot y_0 + \ldots\f$ <br><br>
/// \details we can represent this in linear algebra as the following, <br><br>
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br>
/// let \f$Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]\f$ <br><br>
///
/// then \f$\text{dot}(X, Y)=X \cdot Y^T\f$ <br><br>
///
/// \param x first vector
/// \param y second vector
template<typename genType, size_t...i>
constexpr genType dot(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return ((x[i] * y[i]) + ...); }
// length2 -------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns the squared length of vector \f$x\f$, i.e., \f$x_0^2 + x_1^2 + \ldots\f$
///
/// \returns the squared length of vector \f$x\f$, i.e., \f$x_0^2 + x_1^2 + \ldots\f$ <br><br>
/// \details we can represent this in linear algebra as the following, <br><br>
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br><br>
///
/// then \f$\text{length2}(X)=X \cdot X^T\f$ <br><br>
///
/// \param x the vector
template<typename genType, size_t...i>
constexpr genType length2(const vector<genType, i...>& x)
{ return fennec::dot(x, x); }
// length --------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns the length of vector \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$
///
/// \returns the length of vector \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$<br><br>
/// \details we can represent this in linear algebra as the following, <br><br>
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br><br>
///
/// then, \f$\text{length}(X)=\left|\left|X\right|\right|\f$ <br><br>
///
/// \param x the vector
template<typename genType, size_t...i>
constexpr genType length(const vector<genType, i...>& x) { return fennec::sqrt(fennec::length2(x)); }
// distance ------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns the length of vector \f$x\f$, i.e., \f$\sqrt{x_0^2 + x_1^2 + \ldots}\f$
///
/// \returns the distance between \f$p_0\f$ and \f$p_1\f$, i.e., \f$\left|{p_1-p_0}\right|\f$
/// \details we can represent this in linear algebra as the following, <br><br>
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br>
/// let \f$Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]\f$ <br><br>
///
/// then \f$\text{distance}(X, Y)=\left|\left|Y-X\right|\right|\f$ <br><br>
///
/// \param p0 first vector
/// \param p1 second vector
template<typename genType, size_t...i>
constexpr genType distance(const vector<genType, i...>& p0, const vector<genType, i...>& p1)
{ return fennec::length(p1 - p0); }
// cross ---------------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns the cross product of \f$x\f$ and \f$y\f$, i.e.,
/// \f$\left({x_1 \cdot y_2 - y_1 \cdot x_2, x_2 \cdot y_0 - y_2 \cdot x_0, x_0 \cdot y_1 - y_0 \cdot x_1}\right)\f$
///
/// \returns the cross product of \f$x\f$ and \f$y\f$, i.e.,
/// \f$\left({x_1 \cdot y_2 - y_1 \cdot x_2, x_2 \cdot y_0 - y_2 \cdot x_0, x_0 \cdot y_1 - y_0 \cdot x_1}\right)\f$ <br><br>
/// \details we can represent this in linear algebra as the following, <br><br>
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br>
/// let \f$Y=\left[\begin{array}\\ y_0 \\ y_1 \\ \vdots \\ y_N \end{array}\right]\f$ <br><br>
///
/// then \f$\text{cross}(X, Y)=X \times Y\f$ <br><br>
///
/// \param x first vector
/// \param y second vector
template<typename genType, size_t...i> requires(sizeof...(i) == 3)
constexpr vector<genType, i...> cross(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genType, i...>(x[1]*y[2]-y[1]*x[2], x[2]*y[0]-y[2]*x[0], x[0]*y[1]-y[0]*x[1]); }
// normalize -----------------------------------------------------------------------------------------------------------
///
///
/// \brief Returns a vector in the same direction as \f$x\f$, but with a length of \f$1\f$, i.e.
///
/// \returns a vector in the same direction as \f$x\f$, but with a length of \f$1\f$, i.e.\f$\frac{x}{||x||}<br><br>
/// \details we can represent this in linear algebra as the following, <br><br>
/// let \f$X=\left[\begin{array}\\ x_0 \\ x_1 \\ \vdots \\ x_N \end{array}\right]\f$ <br><br>
///
/// then, \f$\text{length}(X)=\frac{X}{\left|\left|X\right|\right|}\f$ <br><br>
///
/// \param x
template<typename genType, size_t...i>
constexpr vector<genType, i...> normalize(const vector<genType, i...>& x)
{ return x / fennec::length(x); }
// faceforward ---------------------------------------------------------------------------------------------------------
///
///
/// \brief If \f$\text{dot}(Nref, I)<0\f$ return \f$N\f$, otherwise return \f$-N\f$.
///
/// \returns \f$N\f$ if \f$\text{dot}(Nref,I)<0\f$, otherwise, returns \f$-N\f$.<br><br>
///
/// \param N the vector
/// \param I the incident
/// \param Nref the reference
template<typename genType, size_t...i>
constexpr vector<genType, i...> faceforward(const vector<genType, i...>& N, const vector<genType, i...>& I, const vector<genType, i...>& Nref)
{ return fennec::dot(Nref, I) < 0 ? N : -N; }
// reflect -------------------------------------------------------------------------------------------------------------
///
///
/// \brief For the incident vector \f$I\f$ and surface orientation \f$N\f$, returns the reflection direction.
///
/// \returns The reflection direction, given the incident vector \f$I\f$ and surface orientation \f$N\f$ <br><br>
/// \details We can express this as, <br><br>
/// \f$\text{reflect}(I, N) = I - 2 N \cdot \text{dot}(N, I)\f$ <br><br>
///
/// \param I the incident
/// \param N the surface orientation
template<typename genType, size_t...i>
constexpr vector<genType, i...> reflect(const vector<genType, i...>& I, const vector<genType, i...>& N)
{ return I - 2.0 * fennec::dot(N, I) * N; }
// refract -------------------------------------------------------------------------------------------------------------
///
///
/// \brief or the incident vector \f$I\f$ and surface normal \f$N\f$, and the ratio of indices of refraction \f$eta\f$,
/// return the refraction vector.
///
/// \returns The refraction vector, given the incident vector \f$I\f$, surface normal \f$N\f$, and ratio \f$eta\f$.<br><br>
/// \details The result is computed by the refraction equation, <br><br>
/// let \f$k=1.0-eta^2 \cdot (1.0 - \text{dot}(N, I)^2)\f$ <br>
/// then, \f$\text{refract}(I, N, eta)=\begin{cases} 0.0 & k<0.0, \\ eta \cdot I - N \cdot (eta \cdot \text{dot}(N, I) + \sqrt{k}) \end{cases}\f$ <br><br>
///
/// \param I the incident
/// \param N the surface normal
/// \param eta the ratio of indices of refraction
template<typename genType, size_t...i>
constexpr vector<genType, i...> refract(const vector<genType, i...>& I, const vector<genType, i...>& N, genType eta)
{ genType ndi = fennec::dot(N, I);
genType k = 1.0 - eta * eta * (1.0 - ndi * ndi);
return (k < 0.0) ? 0.0 : eta * I - N * (eta * ndi + fennec::sqrt(k)); }
}
#endif // FENNEC_MATH_GEOMETRIC_H

View File

@ -0,0 +1,89 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file math.h
/// \brief main math header which includes the main modules
///
///
/// \details This header includes the following modules of \ref page_fennec_math :
/// - \ref page_fennec_math_scalar
/// - \ref page_fennec_math_vector
/// - \ref page_fennec_math_trigonometric
///
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_MATH_H
#define FENNEC_MATH_H
///
///
///
/// \page page_fennec_math Math Library
///
/// The \ref fennec Math Library is composed of the modules listed in below.
/// The overarching goal of this math library is to implement the math types and functions of the
/// [OpenGL 4.6 Shading Language Specification](https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.60.pdf).
///
/// \section page_fennec_math_topics Topics
/// - \subpage page_fennec_math_set_theory
///
/// \section page_fennec_math_data_types Data Types
///
/// - \subpage page_fennec_math_scalar
/// - \subpage page_fennec_math_vector
/// - \subpage page_fennec_math_matrix
///
/// \section page_fennec_math_functions Functions
///
/// - \subpage page_fennec_math_common
/// - \subpage page_fennec_math_exponential
/// - \subpage page_fennec_math_geometric
/// - \subpage page_fennec_math_trigonometric
///
///
///
///
///
/// \page page_fennec_math_set_theory Set Theory
///
/// Binary Mathematics, like most branches of Mathematics, is built, foundationally, upon Set Theory. Set Theory is
/// the branch of Mathematics that studies Sets. Sets contain a collection of elements which may be numbers, or other
/// mathematical values and structures.
///
/// Set definitions for all mathematical structures in the \ref page_fennec_math "Fennec Math Library" are present in
/// their respective pages.
///
///
#include <fennec/math/swizzle.h>
#include <fennec/math/trigonometric.h>
#include <fennec/math/vector.h>
#include <fennec/math/vector_traits.h>
#endif // FENNEC_MATH_H

View File

@ -0,0 +1,381 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file matrix.h
/// \brief the \ref page_fennec_math_matrix
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
///
///
///
/// \page page_fennec_math_matrix Matrices
///
///
///
///
#ifndef MATRIX_H
#define MATRIX_H
#include <fennec/math/detail/__fwd.h>
#include <fennec/containers/array.h>
#include <fennec/math/geometric.h>
#include <fennec/math/vector.h>
#include <fennec/math/vector_traits.h>
namespace fennec
{
///
/// \brief returns a **copy** of the column \f$i\f$ of matrix \f$m\f$
/// \tparam scalar the base scalar type
/// \tparam rows number of rows in the matrix
/// \tparam cols indices of the columns in the matrix
/// \param m the matrix
/// \param i the index of the row
/// \returns a **copy** of the column at index \f$i\f$
template<typename scalar, size_t rows, size_t...cols>
constexpr vec<scalar, rows> column(const matrix<scalar, rows, cols...>& m, size_t i) noexcept
{ return m[i]; }
///
/// \brief returns a **copy** of the row \f$i\f$ of matrix \f$m\f$
/// \tparam scalar the base scalar type
/// \tparam rows number of rows in the matrix
/// \tparam cols indices of the columns in the matrix
/// \param m the matrix
/// \param i the index of the row
/// \returns a **copy** of the row at index \f$i\f$
template<typename scalar, size_t rows, size_t...cols>
constexpr vec<scalar, sizeof...(cols)> row(const matrix<scalar, rows, cols...>& m, size_t i) noexcept
{ return vec<scalar, sizeof...(cols)>(m[cols][i]...); }
template<size_t rows, size_t cols> using tmat = mat<float_t, rows, cols>;
using mat2 = tmat<2, 2>;
using mat3 = tmat<3, 3>;
using mat4 = tmat<4, 4>;
using mat2x2 = tmat<2, 2>;
using mat2x3 = tmat<2, 3>;
using mat2x4 = tmat<2, 4>;
using mat3x2 = tmat<3, 2>;
using mat3x3 = tmat<3, 3>;
using mat3x4 = tmat<3, 4>;
using mat4x2 = tmat<4, 2>;
using mat4x3 = tmat<4, 3>;
using mat4x4 = tmat<4, 4>;
template<size_t rows, size_t cols> using tdmat = mat<float_t, rows, cols>;
using dmat2 = tdmat<2, 2>;
using dmat3 = tdmat<3, 3>;
using dmat4 = tdmat<4, 4>;
using dmat2x2 = tdmat<2, 2>;
using dmat2x3 = tdmat<2, 3>;
using dmat2x4 = tdmat<2, 4>;
using dmat3x2 = tdmat<3, 2>;
using dmat3x3 = tdmat<3, 3>;
using dmat3x4 = tdmat<3, 4>;
using dmat4x2 = tdmat<4, 2>;
using dmat4x3 = tdmat<4, 3>;
using dmat4x4 = tdmat<4, 4>;
///
///
/// \brief
/// \tparam ScalarT
/// \tparam RowsV
/// \tparam ColIndicesV
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV>
struct matrix
{
// Assertions ==========================================================================================================
static_assert(is_arithmetic_v<ScalarT> or is_bool_v<ScalarT>);
// Typedefs & Constants ================================================================================================
///
/// \brief number of rows in the matrix
static constexpr size_t rows = RowsV;
///
/// \brief number of columns in the matrix
static constexpr size_t columns = sizeof...(ColIndicesV);
///
/// \brief number of total components
static constexpr size_t num_components = rows * columns;
///
/// \brief vector class correspondant to the rows
using row_t = vec<ScalarT, columns>;
///
/// \brief vector class correspondant to the columns
using column_t = vec<ScalarT, rows>;
///
/// \brief base scalar type
using scalar_t = ScalarT;
///
/// \brief alias for this matrix type
using matrix_t = matrix;
///
/// \brief alias for the transpose matrix type
using transpose_t = mat<ScalarT, columns, rows>;
///
/// \brief matrix array data
array<column_t, columns> data;
// Constructors ========================================================================================================
/// \name Constructors
/// @{
///
/// \brief default constructor, initializes elements with 0
///
/// \details
constexpr matrix()
: data{ scalar_t(0) }{}
///
/// \brief copy constructor
///
/// \details
/// \param mat matrix to copy
constexpr matrix(const matrix_t& mat)
: data{ mat.data } {}
///
/// \brief move constructor
///
/// \details
/// \param mat matrix to move
constexpr matrix(matrix_t&& mat)
: data{ mat.data } {}
///
/// \brief scalar constructor, initializes a diagonal matrix with a scale of \p s
///
/// \details
/// This function creates a diagonal matrix such that ```vec3(2.0f)``` would result in a matrix
/// <table>
/// <caption id="fennec_table_matrix_diagonal"></caption>
/// <tr><th> <th> 0 <th> 1 <th> 2
/// <tr><th> 0 <td>2.0<td>0.0<td>0.0
/// <tr><th> 1 <td>0.0<td>2.0<td>0.0
/// <tr><th> 2 <td>0.0<td>0.0<td>2.0
/// </table><br><br>
///
/// \param s scalar value
///
constexpr matrix(scalar_t s)
{ (((ColIndicesV < rows) ? data[ColIndicesV][ColIndicesV] = s : 0), ...); }
///
/// \brief Piece-wise constructor
///
/// \details
/// \tparam ArgsT
/// \param args
template<typename...ArgsT> requires(total_component_count_v<ArgsT...> == num_components)
constexpr matrix(ArgsT&&...args)
{ matrix::__construct(std::forward<ArgsT>(args)...); }
/// @}
// Assignment Operators ================================================================================================
/// \name Assignment Operators
/// @{
///
/// \brief copy assignment operator
///
/// \details
/// \returns a reference to **this** after copying the contents of \p rhs
/// \param rhs the matrix to copy
constexpr matrix_t& operator=(const matrix_t& rhs)
{ data = rhs.data; return *this; }
///
/// \brief move assignment operator
///
/// \details
/// \returns a reference to **this** after moving the contents of \p rhs
/// \param rhs the matrix to move
constexpr matrix_t& operator=(matrix_t&& rhs) noexcept
{ data = rhs.data; return *this; }
/// @}
// Access Operators ====================================================================================================
/// \name Access Operator
/// @{
///
/// \copydetails matrix::operator[](size_t) const
constexpr column_t& operator[](size_t i)
{ assert(i < rows); return data[i]; }
///
/// \brief returns the column at index \f$i\f$
///
/// \details
/// \param i the index
/// \returns the column at index \f$i\f$
constexpr const column_t& operator[](size_t i) const
{ assert(i < rows); return data[i]; }
///
/// \fn matrix::operator()(size_t, size_t)
/// \copydetails matrix::operator()(size_t, size_t) const
constexpr scalar_t& operator()(size_t i, size_t j)
{ assert(i < rows && j < columns); return data[i][j]; }
///
/// \brief returns the cell in row \p j column \p i
/// \param i the column
/// \param j the row
/// \returns the cell at the specified index.
constexpr scalar_t operator()(size_t i, size_t j) const
{ assert(i < rows && j < columns); return data[i][j]; }
/// @}
// Scalar Operators ====================================================================================================
/// \name Scalar Operators
/// @{
/// @}
// Vector Operators ====================================================================================================
/// \name \ref matrix_t "matrix" \ref fennec::vector "vector" Operators
/// @{
///
/// \brief performs a linear algebraic multiply
/// \param lhs the matrix
/// \param rhs the vector
/// \returns a vector containing the dot products of \f$rhs\f$ with each row of \f$lhs\f$
constexpr friend column_t operator*(const matrix_t& lhs, const row_t& rhs)
{ return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> column_t
{ return column_t(fennec::dot(fennec::row(lhs, i), rhs) ...); }(make_index_sequence<rows>{}); }
///
/// \brief performs a linear algebraic multiply
/// \param lhs the vector
/// \param rhs the matrix
/// \returns a vector containing the dot products of \f$lhs\f$ with each column of \f$rhs\f$
constexpr friend row_t operator*(const column_t& lhs, const matrix_t& rhs)
{ return row_t(fennec::dot(fennec::column(rhs, ColIndicesV), lhs) ...); }
/// @}
// Matrix Operators ====================================================================================================
/// \name \ref matrix_t "matrix" \ref matrix_t "matrix" Operators
/// @{
///
/// \brief performs a linear algebraic matrix multiplication
/// \param lhs the rows to multiply with
/// \param rhs the columns to multiply with
constexpr friend matrix_t operator*(const matrix_t& lhs, const transpose_t& rhs)
{ return [lhs, rhs]<size_t...i>(index_sequence<i...>) -> matrix_t
{ return matrix_t(rhs * fennec::row(lhs, i)...); }(make_index_sequence<rows>{}); }
constexpr friend bool operator==(const matrix_t& lhs, const matrix_t& rhs)
{ return lhs.data == rhs.data; }
constexpr friend bool operator!=(const matrix_t& lhs, const matrix_t& rhs)
{ return lhs.data != rhs.data; }
/// @}
// Helpers =============================================================================================================
private:
template<size_t i0 = 0>
constexpr void __construct() { }
template<size_t i0 = 0, typename HeadT, typename...ArgsT>
constexpr void __construct(HeadT&& head, ArgsT&&...args)
{ matrix::__insert(head); matrix::__construct<i0 + component_count_v<HeadT>>(std::forward<ArgsT>(args)...); }
template<size_t i0 = 0>
constexpr void __insert(scalar_t s)
{ data[i0 / columns][i0 % columns] = s; }
template<size_t i0 = 0, typename OScalarT> requires(is_arithmetic_v<OScalarT>)
constexpr void __insert(OScalarT s)
{ data[i0 / columns][i0 % columns] = scalar_t(s); }
template<size_t i0 = 0, size_t...i>
constexpr void __insert(const vector<scalar_t, i...>& v)
{ (matrix::__insert<i0 + i>(v[i]), ...); }
};
}
#endif //MATRIX_H

View File

@ -0,0 +1,98 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file relational.h
/// \brief \ref page_fennec_math_relational
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_MATH_RELATIONAL_H
#define FENNEC_MATH_RELATIONAL_H
#include <fennec/lang/types.h>
namespace fennec
{
template<typename genType, typename genBType = bool_t>
constexpr genBType lessThan(genType x, genType y)
{ return x < y; }
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> lessThan(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] < y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType lessThanEqual(genType x, genType y)
{ return x <= y; }
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> lessThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] <= y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType greaterThan(genType x, genType y)
{ return x > y; }
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> greaterThan(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] > y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType greaterThanEqual(genType x, genType y)
{ return x >= y; }
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> greaterThanEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] >= y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType equal(genType x, genType y)
{ return x == y; }
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> equal(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] == y[i]...); }
template<typename genType, typename genBType = bool_t>
constexpr genBType notEqual(genType x, genType y)
{ return x != y; }
template<typename genType, typename genBType = bool_t, size_t...i>
constexpr vector<genBType, i...> notEqual(const vector<genType, i...>& x, const vector<genType, i...>& y)
{ return vector<genBType, i...>(x[i] != y[i]...); }
template<typename genBType = bool_t, size_t...i>
constexpr genBType any(const vector<genBType, i...>& x)
{ return (x[i] || ...); }
template<typename genBType = bool_t, size_t...i>
constexpr genBType all(const vector<genBType, i...>& x)
{ return (x[i] && ...); }
}
#endif // FENNEC_MATH_RELATIONAL_H

View File

@ -0,0 +1,70 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file scalar.h
/// \brief the \ref page_fennec_math_scalar
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_MATH_SCALAR_H
#define FENNEC_MATH_SCALAR_H
#include <fennec/lang/types.h>
///
///
///
/// \page page_fennec_math_scalar Scalars
/// \anchor scalar
///
/// The \ref fennec Library considers any type that passes ```is_arithmetic<T>``` to be a \ref scalar "Scalar." Bools are
/// supported as a logical type.
///
/// The GLSL Specification, and \ref fennec respectively, defines the following scalar types:
///
/// | Type | Meaning |
/// |----------|------------------------------|
/// |\c bool | \copybrief fennec::bool_t |
/// |\c int | \copybrief fennec::int_t |
/// |\c uint | \copybrief fennec::uint_t |
/// |\c float | \copybrief fennec::float_t |
/// |\c double | \copybrief fennec::double_t |
///
///
///
#include <fennec/math/detail/__fwd.h>
#include <fennec/math/detail/__types.h>
namespace fennec
{
///
/// \brief an unsigned integer
using uint = unsigned int;
}
#endif //TYPES_H

View File

@ -0,0 +1,86 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file swizzle.h
/// \brief part of the \ref page_fennec_math_vector,
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef SWIZZLE_H
#define SWIZZLE_H
#include <fennec/lang/sequences.h>
#include <fennec/math/swizzle_storage.h>
namespace fennec
{
///
///
/// \brief Structure for Handling Vector Swizzling
///
/// \details
/// \tparam VectorT Vector Type
/// \tparam DataT Base Data Type
/// \tparam ScalarT Scalar Base Type
/// \tparam IndicesV Swizzle Indices
template<typename VectorT, typename DataT, typename ScalarT, size_t...IndicesV>
struct swizzle : public detail::swizzle_storage<DataT, ScalarT, IndicesV...>
{
public:
///
/// \brief alias for the scalar type
using scalar_t = ScalarT;
///
/// \name aliases for the size
/// @{
inline static constexpr size_t dimension = sizeof...(IndicesV); ///< \brief dimension of the swizzle
inline static constexpr size_t num_components = sizeof...(IndicesV); ///< \brief number of components
inline static constexpr size_t size = sizeof...(IndicesV); ///< \brief size of the swizzle
inline static constexpr size_t N = sizeof...(IndicesV); ///< \brief size of the swizzle
/// @}
///
/// \brief Decay the Swizzle into a Vector
/// \return The Value of the Swizzle as a Vector
constexpr VectorT decay() const { VectorT res; return decay_impl(res, make_index_sequence<size>{}); }
///
/// \brief Vector Cast Operator
/// \returns The Value of the Swizzle as a Vector
constexpr explicit operator VectorT() const { return decay(); }
swizzle() = default;
private:
template<size_t...VecIndicesV>
constexpr VectorT& decay_impl(VectorT& vec, index_sequence<VecIndicesV...>) { return ((vec[VecIndicesV] = this->data[IndicesV]), ..., vec); }
};
}
#endif //SWIZZLE_H

View File

@ -0,0 +1,58 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef SWIZZLE_STORAGE_H
#define SWIZZLE_STORAGE_H
namespace fennec
{
namespace detail
{
///
///
/// \brief Backing storage struct for \ref fennec::swizzle "swizzle"
/// \tparam DataT Data Type
/// \tparam ScalarT Element Types
/// \tparam IndicesV Swizzle Order
template<typename DataT, typename ScalarT, size_t...IndicesV>
struct swizzle_storage
{
///
/// \brief an array containing the indices of this swizzle
inline static constexpr size_t indices[] = { IndicesV... };
///
/// \brief an array containing the scalar values of this swizzle
DataT data;
///
/// \brief element access, returns a copy of the value at index \p i
/// \param i the index
/// \returns a copy of the scalar value at index \p i
constexpr ScalarT operator[](size_t i) const noexcept { return data[indices[i]]; }
};
}
}
#endif //SWIZZLE_STORAGE_H

View File

@ -0,0 +1,455 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file trigonometric.h
/// \brief the \ref page_fennec_math_trigonometric
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_MATH_TRIGONOMETRIC_H
#define FENNEC_MATH_TRIGONOMETRIC_H
///
///
///
/// \page page_fennec_math_trigonometric Trigonometry
///
/// \brief The fennec Trigonometry Module
///
///
///
/// \section section_fennec_conversions Angle Conversions
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_angle_conversions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::degrees(genType) "genFType degrees(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::degrees(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::radians(genType) "genFType radians(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::radians(genType)
///
/// </table>
///
///
///
/// \section section_fennec_trigonometric_functions Trigonometry
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_angle_conversions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::sin(genType) "genFType sin(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::sin(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::cos(genType) "genFType cos(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::cos(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::tan(genType) "genFType tan(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::tan(genType)
///
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::asin(genType) "genFType asin(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::asin(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::acos(genType) "genFType acos(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::acos(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::atan(genType) "genFType atan(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::atan(genType)
///
/// </table>
///
///
///
/// \section section_fennec_hyperbolic_functions Trigonometry
///
/// <table width="100%" class="fieldtable" id="table_fennec_math_trigonometry_angle_conversions">
/// <tr><th style="vertical-align: top">Syntax
/// <th style="vertical-align: top">Description
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::sinh(genType) "genFType sinh(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::sinh(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::cosh(genType) "genFType cosh(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::cosh(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::tanh(genType) "genFType tanh(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::tanh(genType)
///
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::asinh(genFType) "genFType asinh(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::asinh(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::acosh(genFType) "genFType acosh(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::acosh(genType)
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
/// \ref fennec::atanh(genFType) "genFType atanh(genFType)"
/// <td width="50%" style="vertical-align: top">
/// \copydoc fennec::atanh(genType)
///
/// </table>
///
///
///
///
///
#include <cmath>
namespace fennec
{
// Angle Conversions ===================================================================================================
/// \name Angle Conversions
/// @{
///
/// \brief Converts \f$degrees\f$ to \f$radians\f$, i.e., \f$degrees\cdot\frac{180}{\pi}\f$
///
/// \returns the angle \f$\theta\f$ in \f$radians\f$ <br><br>
/// \details Converts \f$degrees\f$ to \f$radians\f$, i.e., \f$degrees\cdot\frac{180}{\pi}\f$ <br><br>
///
/// \tparam genType floating point type
/// \param degrees the angle \f$\theta\f$ in \f$degrees\f$
template<typename genType>
constexpr genType radians(genType degrees)
{ return degrees * 0.01745329251994329576923690768489; }
template<typename genType, size_t...i>
constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees)
{ return degrees * 0.01745329251994329576923690768489; }
///
/// \brief Converts \f$radians\f$ to \f$degrees\f$, i.e., \f$radians\cdot\frac{\pi}{180}\f$
///
/// \returns the angle \f$\theta\f$ in \f$degrees\f$ <br><br>
/// \details Converts \f$radians\f$ to \f$degrees\f$, i.e., \f$radians\cdot\frac{\pi}{180}\f$ <br><br>
///
/// \tparam genType floating point type
/// \param radians the angle \f$\theta\f$ in \f$radians\f$
template<typename genType>
constexpr genType degrees(genType radians)
{ return radians * 57.29577951308232087679815481410517; }
template<typename genType, size_t...i>
constexpr vector<genType, i...> degrees(const vector<genType, i...>& radians)
{ return radians * 57.29577951308232087679815481410517; }
/// @}
// Trigonometric ======================================================================================================
/// \name Trigonometric Functions
/// @{
///
/// \fn fennec::sin(fennec::genType)
/// \brief The standard trigonometric sine
///
/// \returns the sine of \f$\theta\f$ in the range \f$\left[-1,\,1\right]\f$ <br><br>
/// \details The standard trigonometric sine <br><br>
///
/// \tparam genType floating point type
/// \param x the angle \f$\theta\f$ in \f$radians\f$
template<typename genType>
constexpr genType sin(genType x)
{ return std::sin(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> sin(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sin(x[i]) ...); }
///
/// \fn fennec::cos(fennec::genType)
/// \brief The Standard Trigonometric Cosine
///
/// \returns the cosine of \f$\theta\f$ in the range \f$\left[-1,\,1\right]\f$ <br><br>
/// \details The Standard Trigonometric Cosine <br><br>
///
/// \tparam genType floating point type
/// \param x the angle \f$\theta\f$ in \f$radians\f$
template<typename genType>
constexpr genType cos(genType x)
{ return std::cos(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> cos(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::cos(x[i]) ...); }
///
/// \fn fennec::tan(fennec::genType)
/// \brief The Standard Trigonometric Tangent
///
/// \returns The Tangent of \f$\theta\f$ in the Range \f$\left[-\inf,\,\inf\right]\f$<br><br>
/// \details The Standard Trigonometric Tangent <br><br>
///
/// \tparam genType floating point type
/// \param x The Angle \f$\theta\f$ in \f$radians\f$
template<typename genType>
constexpr genType tan(genType x)
{ return std::tan(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> tan(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::tan(x[i]) ...); }
/// @}
/// \name Inverse Trigonometric Functions
/// @{
///
/// \fn fennec::asin(fennec::genType)
/// \brief Arc Sine. Returns an angle \f$\theta\f$ whose sine is /a x.
///
/// \returns an angle \f$\theta\f$ whose sine is /a x. <br><br>
/// \details Arc Sine. The range of values returned by this functions is
/// \f$\left[-\pi/2,\pi/2\right]\f$. Results are undefined if \f$\left|x\right|\,>\,1\f$. <br><br>
///
/// \tparam genType floating point type
/// \param x The Sine Value produced by \f$\theta\f$
template<typename genType>
constexpr genType asin(genType x)
{ return std::asin(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> asin(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::asin(x[i]) ...); }
///
/// \fn fennec::acos(fennec::genType)
/// \brief Arc Cosine. Returns an angle \f$\theta\f$ whose cosine is /a x.
///
/// \returns an angle \f$\theta\f$ whose cosine is /a x.
/// \details Arc Cosine. The range of values returned by this functions is
/// \f$\left[0,\pi\right]\f$. Results are undefined if \f$\left|x\right|\,>\,1\f$.
///
/// \tparam genType floating point type
/// \param x The Cosine Value produced by \f$\theta\f$
template<typename genType>
constexpr genType acos(genType x)
{ return std::acos(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> acos(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::acos(x[i]) ...); }
///
/// \fn fennec::atan(fennec::genType)
/// \brief Arc Tangent. Returns an angle \f$\theta\f$ whose tangent is /a y_over_x.
///
/// \returns an angle \f$\theta\f$ whose tangent is /a y_over_x.
/// \details Arc Tangent. The range of values returned by this functions is
/// \f$\left[\frac{-\pi}{2},\frac{\pi}{2}\right]\f$. Results are undefined if \f$\left|x\right|\,>\,1\f$.
///
/// \tparam genType floating point type
/// \param y_over_x The Cosine Value produced by \f$\theta\f$
template<typename genType>
constexpr genType atan(genType y_over_x)
{ return std::atan(y_over_x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y_over_x)
{ return vector<genType, i...>(fennec::atan(y_over_x[i]) ...); }
///
/// \fn fennec::tan(fennec::genType, fennec::genType)
/// \brief Arc Tangent. Returns an angle whose tangent is \f$\frac{y}{x}\f$.
///
/// \returns an angle whose tangent is \f$\frac{y}{x}\f$. <br><br>
/// \details Arc Tangent. The signs of \a x and \a y are used to determine what quadrant the angle is in.
/// The range of values returned by this functions is \f$\left[-\pi,\pi\right]\f$ <br><br>
///
/// \tparam genType floating point type
/// \param y The Sine Value produced by \f$\theta\f$
/// \param x The Cosine Value produced by \f$\theta\f$
template<typename genType>
constexpr genType atan(genType y, genType x)
{ return std::atan2(y, x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> atan(const vector<genType, i...>& y, const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::atan(y[i], x[i]) ...); }
/// @}
// Hyperbolic Functions ================================================================================================
/// \name Hyperbolic Functions
/// @{
///
/// \fn fennec::sinh(fennec::genType)
/// \brief Returns the Hyperbolic Sine Function, \f$\frac{{e}^{x}-{e}^{-x}}{2}\f$
///
/// \returns The Hyperbolic Sine of \f$x\f$, \f$\frac{{e}^{x}-{e}^{-x}}{2}\f$ <br><br>
///
/// \tparam genType floating point type
/// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType>
constexpr genType sinh(genType x)
{ return std::sinh(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> sinh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::sinh(x[i]) ...); }
///
/// \fn fennec::cosh(fennec::genType)
/// \brief Returns the Hyperbolic Cosine Function, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$
///
/// \returns The Hyperbolic Cosine of \f$x\f$, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ <br><br>
///
/// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType>
constexpr genType cosh(genType x)
{ return std::cosh(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> cosh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::cosh(x[i]) ...); }
///
/// \fn fennec::tanh(fennec::genType)
/// \brief Returns the Hyperbolic Tangent Function, \f$\frac{\text{sinh}(x)}{\text{cosh}(x)}\f$
///
/// \returns The Hyperbolic Tangent of \f$x\f$, \f$\frac{{e}^{x}+{e}^{-x}}{2}\f$ <br><br>
///
/// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType, size_t...i>
constexpr genType tanh(genType x)
{ return std::tanh(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> tanh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::tanh(x[i]) ...); }
/// @}
/// \name Inverse Hyperbolic Functions
/// @{
///
/// \fn fennec::asinh(fennec::genType)
/// \brief The Inverse Hyperbolic Sine Function
///
/// \returns the value \f$y\f$ that fulfills \f$x=\text{sinh}(y)\f$ <br><br>
/// \details The Inverse Hyperbolic Sine Function <br><br>
///
/// \param x the hyperbolic angle \f$\alpha\f$
template<typename genType, size_t...i>
constexpr genType asinh(genType x)
{ return std::asinh(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> asinh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::asinh(x[i]) ...); }
///
/// \fn fennec::cosh(fennec::genType)
/// \brief The Inverse Hyperbolic Cosine Function
///
/// \returns the value \f$y\f$ that fulfills \f$x=\text{cosh}(y)\f$ <br><br>
/// \details The Inverse Hyperbolic Cosine Function <br><br>
///
/// \param x the hyperbolic angle \f$\alpha\f$
template<typename genType, size_t...i>
constexpr genType acosh(genType x)
{ return std::acosh(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> acosh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::acosh(x[i]) ...); }
///
/// \fn fennec::atan(fennec::genType)
/// \brief The Inverse Hyperbolic Tangent Function
///
/// \returns the value \f$y\f$ that fulfills \f$x=\text{atanh}(y)\f$ <br><br>
/// \details The Inverse Hyperbolic Tangent Function <br><br>
///
/// \param x The Hyperbolic Angle \f$\alpha\f$
template<typename genType, size_t...i>
constexpr genType atanh(genType x)
{ return std::atanh(x); }
template<typename genType, size_t...i>
constexpr vector<genType, i...> atanh(const vector<genType, i...>& x)
{ return vector<genType, i...>(fennec::atanh(x[i]) ...); }
/// @}
}
#endif // FENNEC_MATH_TRIGONOMETRIC_H

1086
include/fennec/math/vector.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef VECTOR_BASE_H
#define VECTOR_BASE_H
#include <fennec/math/detail/__fwd.h>
#include <fennec/math/swizzle.h>
#include <fennec/math/vector_storage.h>
#include <fennec/containers/array.h>
namespace fennec
{
namespace detail
{
///
/// \struct vector_base_type_helper
/// \brief helper class for generating vectors
/// \tparam scalar base scalar type
/// \tparam size size of the vector type
template<typename scalar, size_t size>
struct vector_base_type_helper
{
///
/// \var SizeV
/// \brief size of the vector type
inline static constexpr size_t SizeV = size;
///
/// \typedef ScalarT
/// \brief Base scalar type
using ScalarT = scalar;
///
/// \typedef VectorT
/// \brief Base vector type
using VectorT = vec<ScalarT, SizeV>;
///
/// \typedef DataT
/// \brief Backing array holding the elements
using DataT = array<ScalarT, SizeV>;
///
/// \struct SwizzleGen
/// \brief Helper for generating a swizzle from a set of indices
/// \tparam IndicesV Indices of the vector to pull from
template<size_t...IndicesV> struct SwizzleGen
{
/// \brief generated swizzle type
using type = swizzle<VectorT, DataT, ScalarT, IndicesV...>;
};
///
/// \struct SwizzleGen<IndexV>
/// \brief Partial Specialization for single component swizzles to decay into a scalar
/// \tparam IndexV
template<size_t IndexV> struct SwizzleGen<IndexV>
{
/// \brief decayed scalar type
using type = ScalarT;
};
///
/// \typedef StorageT
/// \brief backing storage type
using StorageT = vector_storage<SizeV, SwizzleGen, DataT>;
};
template<typename ScalarT, size_t SizeV>
using vector_base_type = typename vector_base_type_helper<ScalarT, SizeV>::StorageT;
}
}
#endif //VECTOR_BASE_H

View File

@ -0,0 +1,636 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef VECTOR_STORAGE_H
#define VECTOR_STORAGE_H
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
namespace fennec
{
namespace detail
{
///
/// \struct vector_storage
/// \brief backing storage type for vectors
/// \tparam SizeV size of the vector
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template<size_t SizeV, template<size_t...> class SwizzleGenT, typename DataT> struct vector_storage;
///
/// \struct vector_storage<1, SwizzleGenT, DataT>
/// \brief specialization for single component vectors
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template <template <size_t...> class SwizzleGenT, typename DataT>
struct vector_storage<1, SwizzleGenT, DataT>
{
///
/// \typedef swizzle
/// alias to allow for increased legibility
template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type;
vector_storage() = default;
union {
DataT data;
struct { swizzle<0> x; };
struct { swizzle<0> s; };
struct { swizzle<0> t; };
swizzle<0, 0> xx, rr, ss;
swizzle<0, 0, 0> xxx, rrr, sss;
swizzle<0, 0, 0, 0> xxxx, rrrr, ssss;
};
};
///
/// \struct vector_storage<2, SwizzleGenT, DataT>
/// \brief specialization for two component vectors
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template <template <size_t...> class SwizzleGenT, typename DataT>
struct vector_storage<2, SwizzleGenT, DataT>
{
///
/// \typedef swizzle
/// alias to allow for increased legibility
template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type;
vector_storage() = default;
union {
DataT data;
struct { swizzle<0> x; swizzle<1> y; };
struct { swizzle<0> s; swizzle<1> t; };
struct { swizzle<0> r; swizzle<1> g; };
swizzle<0,0> xx, rr, ss;
swizzle<0,1> xy, rg, st;
swizzle<1,0> yx, gr, ts;
swizzle<1,1> yy, gg, tt;
swizzle<0,0,0> xxx, rrr, sss;
swizzle<0,0,1> xxy, rrg, sst;
swizzle<0,1,0> xyx, rgr, sts;
swizzle<0,1,1> xyy, rgg, stt;
swizzle<1,0,0> yxx, grr, tss;
swizzle<1,0,1> yxy, grg, tst;
swizzle<1,1,0> yyx, ggr, tts;
swizzle<1,1,1> yyy, ggg, ttt;
swizzle<0,0,0,0> xxxx, rrrr, ssss;
swizzle<0,0,0,1> xxxy, rrrg, ssst;
swizzle<0,0,1,0> xxyx, rrgr, ssts;
swizzle<0,0,1,1> xxyy, rrgg, sstt;
swizzle<0,1,0,0> xyxx, rgrr, stss;
swizzle<0,1,0,1> xyxy, rgrg, stst;
swizzle<0,1,1,0> xyyx, rggr, stts;
swizzle<0,1,1,1> xyyy, rggg, sttt;
swizzle<1,0,0,0> yxxx, grrr, tsss;
swizzle<1,0,0,1> yxxy, grrg, tsst;
swizzle<1,0,1,0> yxyx, grgr, tsts;
swizzle<1,0,1,1> yxyy, grgg, tstt;
swizzle<1,1,0,0> yyxx, ggrr, ttss;
swizzle<1,1,0,1> yyxy, ggrg, ttst;
swizzle<1,1,1,0> yyyx, gggr, ttts;
swizzle<1,1,1,1> yyyy, gggg, tttt;
};
};
///
/// \struct vector_storage<3, SwizzleGenT, DataT>
/// \brief specialization for three component vectors
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template <template <size_t...> class SwizzleGenT, typename DataT>
struct vector_storage<3, SwizzleGenT, DataT>
{
///
/// \typedef swizzle
/// alias to allow for increased legibility
template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type;
vector_storage() = default;
union {
DataT data;
struct { swizzle<0> x; swizzle<1> y; swizzle<2> z; };
struct { swizzle<0> s; swizzle<1> t; swizzle<2> p; };
struct { swizzle<0> r; swizzle<1> g; swizzle<2> b; };
swizzle<0,0> xx, rr, ss;
swizzle<0,1> xy, rg, st;
swizzle<0,2> xz, rb, sp;
swizzle<1,0> yx, gr, ts;
swizzle<1,1> yy, gg, tt;
swizzle<1,2> yz, gb, tp;
swizzle<2,0> zx, br, ps;
swizzle<2,1> zy, bg, pt;
swizzle<2,2> zz, bb, pp;
swizzle<0,0,0> xxx, rrr, sss;
swizzle<0,0,1> xxy, rrg, sst;
swizzle<0,0,2> xxz, rrb, ssp;
swizzle<0,1,0> xyx, rgr, sts;
swizzle<0,1,1> xyy, rgg, stt;
swizzle<0,1,2> xyz, rgb, stp;
swizzle<0,2,0> xzx, rbr, sps;
swizzle<0,2,1> xzy, rbg, spt;
swizzle<0,2,2> xzz, rbb, spp;
swizzle<1,0,0> yxx, grr, tss;
swizzle<1,0,1> yxy, grg, tst;
swizzle<1,0,2> yxz, grb, tsp;
swizzle<1,1,0> yyx, ggr, tts;
swizzle<1,1,1> yyy, ggg, ttt;
swizzle<1,1,2> yyz, ggb, ttp;
swizzle<1,2,0> yzx, gbr, tps;
swizzle<1,2,1> yzy, gbg, tpt;
swizzle<1,2,2> yzz, gbb, tpp;
swizzle<2,0,0> zxx, brr, pss;
swizzle<2,0,1> zxy, brg, pst;
swizzle<2,0,2> zxz, brb, psp;
swizzle<2,1,0> zyx, bgr, pts;
swizzle<2,1,1> zyy, bgg, ptt;
swizzle<2,1,2> zyz, bgb, ptp;
swizzle<2,2,0> zzx, bbr, pps;
swizzle<2,2,1> zzy, bbg, ppt;
swizzle<2,2,2> zzz, bbb, ppp;
swizzle<0,0,0,0> xxxx, rrrr, ssss;
swizzle<0,0,0,1> xxxy, rrrg, ssst;
swizzle<0,0,0,2> xxxz, rrrb, sssp;
swizzle<0,0,1,0> xxyx, rrgr, ssts;
swizzle<0,0,1,1> xxyy, rrgg, sstt;
swizzle<0,0,1,2> xxyz, rrgb, sstp;
swizzle<0,0,2,0> xxzx, rrbr, ssps;
swizzle<0,0,2,1> xxzy, rrbg, sspt;
swizzle<0,0,2,2> xxzz, rrbb, sspp;
swizzle<0,1,0,0> xyxx, rgrr, stss;
swizzle<0,1,0,1> xyxy, rgrg, stst;
swizzle<0,1,0,2> xyxz, rgrb, stsp;
swizzle<0,1,1,0> xyyx, rggr, stts;
swizzle<0,1,1,1> xyyy, rggg, sttt;
swizzle<0,1,1,2> xyyz, rggb, sttp;
swizzle<0,1,2,0> xyzx, rgbr, stps;
swizzle<0,1,2,1> xyzy, rgbg, stpt;
swizzle<0,1,2,2> xyzz, rgbb, stpp;
swizzle<0,2,0,0> xzxx, rbrr, spss;
swizzle<0,2,0,1> xzxy, rbrg, spst;
swizzle<0,2,0,2> xzxz, rbrb, spsp;
swizzle<0,2,1,0> xzyx, rbgr, spts;
swizzle<0,2,1,1> xzyy, rbgg, sptt;
swizzle<0,2,1,2> xzyz, rbgb, sptp;
swizzle<0,2,2,0> xzzx, rbbr, spps;
swizzle<0,2,2,1> xzzy, rbbg, sppt;
swizzle<0,2,2,2> xzzz, rbbb, sppp;
swizzle<1,0,0,0> yxxx, grrr, tsss;
swizzle<1,0,0,1> yxxy, grrg, tsst;
swizzle<1,0,0,2> yxxz, grrb, tssp;
swizzle<1,0,1,0> yxyx, grgr, tsts;
swizzle<1,0,1,1> yxyy, grgg, tstt;
swizzle<1,0,1,2> yxyz, grgb, tstp;
swizzle<1,0,2,0> yxzx, grbr, tsps;
swizzle<1,0,2,1> yxzy, grbg, tspt;
swizzle<1,0,2,2> yxzz, grbb, tspp;
swizzle<1,1,0,0> yyxx, ggrr, ttss;
swizzle<1,1,0,1> yyxy, ggrg, ttst;
swizzle<1,1,0,2> yyxz, ggrb, ttsp;
swizzle<1,1,1,0> yyyx, gggr, ttts;
swizzle<1,1,1,1> yyyy, gggg, tttt;
swizzle<1,1,1,2> yyyz, gggb, tttp;
swizzle<1,1,2,0> yyzx, ggbr, ttps;
swizzle<1,1,2,1> yyzy, ggbg, ttpt;
swizzle<1,1,2,2> yyzz, ggbb, ttpp;
swizzle<1,2,0,0> yzxx, gbrr, tpss;
swizzle<1,2,0,1> yzxy, gbrg, tpst;
swizzle<1,2,0,2> yzxz, gbrb, tpsp;
swizzle<1,2,1,0> yzyx, gbgr, tpts;
swizzle<1,2,1,1> yzyy, gbgg, tptt;
swizzle<1,2,1,2> yzyz, gbgb, tptp;
swizzle<1,2,2,0> yzzx, gbbr, tpps;
swizzle<1,2,2,1> yzzy, gbbg, tppt;
swizzle<1,2,2,2> yzzz, gbbb, tppp;
swizzle<2,0,0,0> zxxx, brrr, psss;
swizzle<2,0,0,1> zxxy, brrg, psst;
swizzle<2,0,0,2> zxxz, brrb, pssp;
swizzle<2,0,1,0> zxyx, brgr, psts;
swizzle<2,0,1,1> zxyy, brgg, pstt;
swizzle<2,0,1,2> zxyz, brgb, pstp;
swizzle<2,0,2,0> zxzx, brbr, psps;
swizzle<2,0,2,1> zxzy, brbg, pspt;
swizzle<2,0,2,2> zxzz, brbb, pspp;
swizzle<2,1,0,0> zyxx, bgrr, ptss;
swizzle<2,1,0,1> zyxy, bgrg, ptst;
swizzle<2,1,0,2> zyxz, bgrb, ptsp;
swizzle<2,1,1,0> zyyx, bggr, ptts;
swizzle<2,1,1,1> zyyy, bggg, pttt;
swizzle<2,1,1,2> zyyz, bggb, pttp;
swizzle<2,1,2,0> zyzx, bgbr, ptps;
swizzle<2,1,2,1> zyzy, bgbg, ptpt;
swizzle<2,1,2,2> zyzz, bgbb, ptpp;
swizzle<2,2,0,0> zzxx, bbrr, ppss;
swizzle<2,2,0,1> zzxy, bbrg, ppst;
swizzle<2,2,0,2> zzxz, bbrb, ppsp;
swizzle<2,2,1,0> zzyx, bbgr, ppts;
swizzle<2,2,1,1> zzyy, bbgg, pptt;
swizzle<2,2,1,2> zzyz, bbgb, pptp;
swizzle<2,2,2,0> zzzx, bbbr, ppps;
swizzle<2,2,2,1> zzzy, bbbg, pppt;
swizzle<2,2,2,2> zzzz, bbbb, pppp;
};
};
///
/// \struct vector_storage<4, SwizzleGenT, DataT>
/// \brief specialization for four component vectors
/// \tparam SwizzleGenT generator for swizzles
/// \tparam DataT backing data type
template <template <size_t...> class SwizzleGenT, typename DataT>
struct vector_storage<4, SwizzleGenT, DataT>
{
///
/// \typedef swizzle
/// alias to allow for increased legibility
template<size_t...IndicesV> using swizzle = typename SwizzleGenT<IndicesV...>::type;
vector_storage() = default;
union {
DataT data;
struct { swizzle<0> x; swizzle<1> y; swizzle<2> z; swizzle<3> w; };
struct { swizzle<0> s; swizzle<1> t; swizzle<2> p; swizzle<3> q; };
struct { swizzle<0> r; swizzle<1> g; swizzle<2> b; swizzle<3> a; };
swizzle<0,0> xx, rr, ss;
swizzle<0,1> xy, rg, st;
swizzle<0,2> xz, rb, sp;
swizzle<0,3> xw, ra, sq;
swizzle<1,0> yx, gr, ts;
swizzle<1,1> yy, gg, tt;
swizzle<1,2> yz, gb, tp;
swizzle<1,3> yw, ga, tq;
swizzle<2,0> zx, br, ps;
swizzle<2,1> zy, bg, pt;
swizzle<2,2> zz, bb, pp;
swizzle<2,3> zw, ba, pq;
swizzle<3,0> wx, ar, qs;
swizzle<3,1> wy, ag, qt;
swizzle<3,2> wz, ab, qp;
swizzle<3,3> ww, aa, qq;
swizzle<0,0,0> xxx, rrr, sss;
swizzle<0,0,1> xxy, rrg, sst;
swizzle<0,0,2> xxz, rrb, ssp;
swizzle<0,0,3> xxw, rra, ssq;
swizzle<0,1,0> xyx, rgr, sts;
swizzle<0,1,1> xyy, rgg, stt;
swizzle<0,1,2> xyz, rgb, stp;
swizzle<0,1,3> xyw, rga, stq;
swizzle<0,2,0> xzx, rbr, sps;
swizzle<0,2,1> xzy, rbg, spt;
swizzle<0,2,2> xzz, rbb, spp;
swizzle<0,2,3> xzw, rba, spq;
swizzle<0,3,0> xwx, rar, sqs;
swizzle<0,3,1> xwy, rag, sqt;
swizzle<0,3,2> xwz, rab, sqp;
swizzle<0,3,3> xww, raa, sqq;
swizzle<1,0,0> yxx, grr, tss;
swizzle<1,0,1> yxy, grg, tst;
swizzle<1,0,2> yxz, grb, tsp;
swizzle<1,0,3> yxw, gra, tsq;
swizzle<1,1,0> yyx, ggr, tts;
swizzle<1,1,1> yyy, ggg, ttt;
swizzle<1,1,2> yyz, ggb, ttp;
swizzle<1,1,3> yyw, gga, ttq;
swizzle<1,2,0> yzx, gbr, tps;
swizzle<1,2,1> yzy, gbg, tpt;
swizzle<1,2,2> yzz, gbb, tpp;
swizzle<1,2,3> yzw, gba, tpq;
swizzle<1,3,0> ywx, gar, tqs;
swizzle<1,3,1> ywy, gag, tqt;
swizzle<1,3,2> ywz, gab, tqp;
swizzle<1,3,3> yww, gaa, tqq;
swizzle<2,0,0> zxx, brr, pss;
swizzle<2,0,1> zxy, brg, pst;
swizzle<2,0,2> zxz, brb, psp;
swizzle<2,0,3> zxw, bra, psq;
swizzle<2,1,0> zyx, bgr, pts;
swizzle<2,1,1> zyy, bgg, ptt;
swizzle<2,1,2> zyz, bgb, ptp;
swizzle<2,1,3> zyw, bga, ptq;
swizzle<2,2,0> zzx, bbr, pps;
swizzle<2,2,1> zzy, bbg, ppt;
swizzle<2,2,2> zzz, bbb, ppp;
swizzle<2,2,3> zzw, bba, ppq;
swizzle<2,3,0> zwx, bar, pqs;
swizzle<2,3,1> zwy, bag, pqt;
swizzle<2,3,2> zwz, bab, pqp;
swizzle<2,3,3> zww, baa, pqq;
swizzle<3,0,0> wxx, arr, qss;
swizzle<3,0,1> wxy, arg, qst;
swizzle<3,0,2> wxz, arb, qsp;
swizzle<3,0,3> wxw, ara, qsq;
swizzle<3,1,0> wyx, agr, qts;
swizzle<3,1,1> wyy, agg, qtt;
swizzle<3,1,2> wyz, agb, qtp;
swizzle<3,1,3> wyw, aga, qtq;
swizzle<3,2,0> wzx, abr, qps;
swizzle<3,2,1> wzy, abg, qpt;
swizzle<3,2,2> wzz, abb, qpp;
swizzle<3,2,3> wzw, aba, qpq;
swizzle<3,3,0> wwx, aar, qqs;
swizzle<3,3,1> wwy, aag, qqt;
swizzle<3,3,2> wwz, aab, qqp;
swizzle<3,3,3> www, aaa, qqq;
swizzle<0,0,0,0> xxxx, rrrr, ssss;
swizzle<0,0,0,1> xxxy, rrrg, ssst;
swizzle<0,0,0,2> xxxz, rrrb, sssp;
swizzle<0,0,0,3> xxxw, rrra, sssq;
swizzle<0,0,1,0> xxyx, rrgr, ssts;
swizzle<0,0,1,1> xxyy, rrgg, sstt;
swizzle<0,0,1,2> xxyz, rrgb, sstp;
swizzle<0,0,1,3> xxyw, rrga, sstq;
swizzle<0,0,2,0> xxzx, rrbr, ssps;
swizzle<0,0,2,1> xxzy, rrbg, sspt;
swizzle<0,0,2,2> xxzz, rrbb, sspp;
swizzle<0,0,2,3> xxzw, rrba, sspq;
swizzle<0,0,3,0> xxwx, rrar, ssqs;
swizzle<0,0,3,1> xxwy, rrag, ssqt;
swizzle<0,0,3,2> xxwz, rrab, ssqp;
swizzle<0,0,3,3> xxww, rraa, ssqq;
swizzle<0,1,0,0> xyxx, rgrr, stss;
swizzle<0,1,0,1> xyxy, rgrg, stst;
swizzle<0,1,0,2> xyxz, rgrb, stsp;
swizzle<0,1,0,3> xyxw, rgra, stsq;
swizzle<0,1,1,0> xyyx, rggr, stts;
swizzle<0,1,1,1> xyyy, rggg, sttt;
swizzle<0,1,1,2> xyyz, rggb, sttp;
swizzle<0,1,1,3> xyyw, rgga, sttq;
swizzle<0,1,2,0> xyzx, rgbr, stps;
swizzle<0,1,2,1> xyzy, rgbg, stpt;
swizzle<0,1,2,2> xyzz, rgbb, stpp;
swizzle<0,1,2,3> xyzw, rgba, stpq;
swizzle<0,1,3,0> xywx, rgar, stqs;
swizzle<0,1,3,1> xywy, rgag, stqt;
swizzle<0,1,3,2> xywz, rgab, stqp;
swizzle<0,1,3,3> xyww, rgaa, stqq;
swizzle<0,2,0,0> xzxx, rbrr, spss;
swizzle<0,2,0,1> xzxy, rbrg, spst;
swizzle<0,2,0,2> xzxz, rbrb, spsp;
swizzle<0,2,0,3> xzxw, rbra, spsq;
swizzle<0,2,1,0> xzyx, rbgr, spts;
swizzle<0,2,1,1> xzyy, rbgg, sptt;
swizzle<0,2,1,2> xzyz, rbgb, sptp;
swizzle<0,2,1,3> xzyw, rbga, sptq;
swizzle<0,2,2,0> xzzx, rbbr, spps;
swizzle<0,2,2,1> xzzy, rbbg, sppt;
swizzle<0,2,2,2> xzzz, rbbb, sppp;
swizzle<0,2,2,3> xzzw, rbba, sppq;
swizzle<0,2,3,0> xzwx, rbar, spqs;
swizzle<0,2,3,1> xzwy, rbag, spqt;
swizzle<0,2,3,2> xzwz, rbab, spqp;
swizzle<0,2,3,3> xzww, rbaa, spqq;
swizzle<0,3,0,0> xwxx, rarr, sqss;
swizzle<0,3,0,1> xwxy, rarg, sqst;
swizzle<0,3,0,2> xwxz, rarb, sqsp;
swizzle<0,3,0,3> xwxw, rara, sqsq;
swizzle<0,3,1,0> xwyx, ragr, sqts;
swizzle<0,3,1,1> xwyy, ragg, sqtt;
swizzle<0,3,1,2> xwyz, ragb, sqtp;
swizzle<0,3,1,3> xwyw, raga, sqtq;
swizzle<0,3,2,0> xwzx, rabr, sqps;
swizzle<0,3,2,1> xwzy, rabg, sqpt;
swizzle<0,3,2,2> xwzz, rabb, sqpp;
swizzle<0,3,2,3> xwzw, raba, sqpq;
swizzle<0,3,3,0> xwwx, raar, sqqs;
swizzle<0,3,3,1> xwwy, raag, sqqt;
swizzle<0,3,3,2> xwwz, raab, sqqp;
swizzle<0,3,3,3> xwww, raaa, sqqq;
swizzle<1,0,0,0> yxxx, grrr, tsss;
swizzle<1,0,0,1> yxxy, grrg, tsst;
swizzle<1,0,0,2> yxxz, grrb, tssp;
swizzle<1,0,0,3> yxxw, grra, tssq;
swizzle<1,0,1,0> yxyx, grgr, tsts;
swizzle<1,0,1,1> yxyy, grgg, tstt;
swizzle<1,0,1,2> yxyz, grgb, tstp;
swizzle<1,0,1,3> yxyw, grga, tstq;
swizzle<1,0,2,0> yxzx, grbr, tsps;
swizzle<1,0,2,1> yxzy, grbg, tspt;
swizzle<1,0,2,2> yxzz, grbb, tspp;
swizzle<1,0,2,3> yxzw, grba, tspq;
swizzle<1,0,3,0> yxwx, grar, tsqs;
swizzle<1,0,3,1> yxwy, grag, tsqt;
swizzle<1,0,3,2> yxwz, grab, tsqp;
swizzle<1,0,3,3> yxww, graa, tsqq;
swizzle<1,1,0,0> yyxx, ggrr, ttss;
swizzle<1,1,0,1> yyxy, ggrg, ttst;
swizzle<1,1,0,2> yyxz, ggrb, ttsp;
swizzle<1,1,0,3> yyxw, ggra, ttsq;
swizzle<1,1,1,0> yyyx, gggr, ttts;
swizzle<1,1,1,1> yyyy, gggg, tttt;
swizzle<1,1,1,2> yyyz, gggb, tttp;
swizzle<1,1,1,3> yyyw, ggga, tttq;
swizzle<1,1,2,0> yyzx, ggbr, ttps;
swizzle<1,1,2,1> yyzy, ggbg, ttpt;
swizzle<1,1,2,2> yyzz, ggbb, ttpp;
swizzle<1,1,2,3> yyzw, ggba, ttpq;
swizzle<1,1,3,0> yywx, ggar, ttqs;
swizzle<1,1,3,1> yywy, ggag, ttqt;
swizzle<1,1,3,2> yywz, ggab, ttqp;
swizzle<1,1,3,3> yyww, ggaa, ttqq;
swizzle<1,2,0,0> yzxx, gbrr, tpss;
swizzle<1,2,0,1> yzxy, gbrg, tpst;
swizzle<1,2,0,2> yzxz, gbrb, tpsp;
swizzle<1,2,0,3> yzxw, gbra, tpsq;
swizzle<1,2,1,0> yzyx, gbgr, tpts;
swizzle<1,2,1,1> yzyy, gbgg, tptt;
swizzle<1,2,1,2> yzyz, gbgb, tptp;
swizzle<1,2,1,3> yzyw, gbga, tptq;
swizzle<1,2,2,0> yzzx, gbbr, tpps;
swizzle<1,2,2,1> yzzy, gbbg, tppt;
swizzle<1,2,2,2> yzzz, gbbb, tppp;
swizzle<1,2,2,3> yzzw, gbba, tppq;
swizzle<1,2,3,0> yzwx, gbar, tpqs;
swizzle<1,2,3,1> yzwy, gbag, tpqt;
swizzle<1,2,3,2> yzwz, gbab, tpqp;
swizzle<1,2,3,3> yzww, gbaa, tpqq;
swizzle<1,3,0,0> ywxx, garr, tqss;
swizzle<1,3,0,1> ywxy, garg, tqst;
swizzle<1,3,0,2> ywxz, garb, tqsp;
swizzle<1,3,0,3> ywxw, gara, tqsq;
swizzle<1,3,1,0> ywyx, gagr, tqts;
swizzle<1,3,1,1> ywyy, gagg, tqtt;
swizzle<1,3,1,2> ywyz, gagb, tqtp;
swizzle<1,3,1,3> ywyw, gaga, tqtq;
swizzle<1,3,2,0> ywzx, gabr, tqps;
swizzle<1,3,2,1> ywzy, gabg, tqpt;
swizzle<1,3,2,2> ywzz, gabb, tqpp;
swizzle<1,3,2,3> ywzw, gaba, tqpq;
swizzle<1,3,3,0> ywwx, gaar, tqqs;
swizzle<1,3,3,1> ywwy, gaag, tqqt;
swizzle<1,3,3,2> ywwz, gaab, tqqp;
swizzle<1,3,3,3> ywww, gaaa, tqqq;
swizzle<2,0,0,0> zxxx, brrr, psss;
swizzle<2,0,0,1> zxxy, brrg, psst;
swizzle<2,0,0,2> zxxz, brrb, pssp;
swizzle<2,0,0,3> zxxw, brra, pssq;
swizzle<2,0,1,0> zxyx, brgr, psts;
swizzle<2,0,1,1> zxyy, brgg, pstt;
swizzle<2,0,1,2> zxyz, brgb, pstp;
swizzle<2,0,1,3> zxyw, brga, pstq;
swizzle<2,0,2,0> zxzx, brbr, psps;
swizzle<2,0,2,1> zxzy, brbg, pspt;
swizzle<2,0,2,2> zxzz, brbb, pspp;
swizzle<2,0,2,3> zxzw, brba, pspq;
swizzle<2,0,3,0> zxwx, brar, psqs;
swizzle<2,0,3,1> zxwy, brag, psqt;
swizzle<2,0,3,2> zxwz, brab, psqp;
swizzle<2,0,3,3> zxww, braa, psqq;
swizzle<2,1,0,0> zyxx, bgrr, ptss;
swizzle<2,1,0,1> zyxy, bgrg, ptst;
swizzle<2,1,0,2> zyxz, bgrb, ptsp;
swizzle<2,1,0,3> zyxw, bgra, ptsq;
swizzle<2,1,1,0> zyyx, bggr, ptts;
swizzle<2,1,1,1> zyyy, bggg, pttt;
swizzle<2,1,1,2> zyyz, bggb, pttp;
swizzle<2,1,1,3> zyyw, bgga, pttq;
swizzle<2,1,2,0> zyzx, bgbr, ptps;
swizzle<2,1,2,1> zyzy, bgbg, ptpt;
swizzle<2,1,2,2> zyzz, bgbb, ptpp;
swizzle<2,1,2,3> zyzw, bgba, ptpq;
swizzle<2,1,3,0> zywx, bgar, ptqs;
swizzle<2,1,3,1> zywy, bgag, ptqt;
swizzle<2,1,3,2> zywz, bgab, ptqp;
swizzle<2,1,3,3> zyww, bgaa, ptqq;
swizzle<2,2,0,0> zzxx, bbrr, ppss;
swizzle<2,2,0,1> zzxy, bbrg, ppst;
swizzle<2,2,0,2> zzxz, bbrb, ppsp;
swizzle<2,2,0,3> zzxw, bbra, ppsq;
swizzle<2,2,1,0> zzyx, bbgr, ppts;
swizzle<2,2,1,1> zzyy, bbgg, pptt;
swizzle<2,2,1,2> zzyz, bbgb, pptp;
swizzle<2,2,1,3> zzyw, bbga, pptq;
swizzle<2,2,2,0> zzzx, bbbr, ppps;
swizzle<2,2,2,1> zzzy, bbbg, pppt;
swizzle<2,2,2,2> zzzz, bbbb, pppp;
swizzle<2,2,2,3> zzzw, bbba, pppq;
swizzle<2,2,3,0> zzwx, bbar, ppqs;
swizzle<2,2,3,1> zzwy, bbag, ppqt;
swizzle<2,2,3,2> zzwz, bbab, ppqp;
swizzle<2,2,3,3> zzww, bbaa, ppqq;
swizzle<2,3,0,0> zwxx, barr, pqss;
swizzle<2,3,0,1> zwxy, barg, pqst;
swizzle<2,3,0,2> zwxz, barb, pqsp;
swizzle<2,3,0,3> zwxw, bara, pqsq;
swizzle<2,3,1,0> zwyx, bagr, pqts;
swizzle<2,3,1,1> zwyy, bagg, pqtt;
swizzle<2,3,1,2> zwyz, bagb, pqtp;
swizzle<2,3,1,3> zwyw, baga, pqtq;
swizzle<2,3,2,0> zwzx, babr, pqps;
swizzle<2,3,2,1> zwzy, babg, pqpt;
swizzle<2,3,2,2> zwzz, babb, pqpp;
swizzle<2,3,2,3> zwzw, baba, pqpq;
swizzle<2,3,3,0> zwwx, baar, pqqs;
swizzle<2,3,3,1> zwwy, baag, pqqt;
swizzle<2,3,3,2> zwwz, baab, pqqp;
swizzle<2,3,3,3> zwww, baaa, pqqq;
swizzle<3,0,0,0> wxxx, arrr, qsss;
swizzle<3,0,0,1> wxxy, arrg, qsst;
swizzle<3,0,0,2> wxxz, arrb, qssp;
swizzle<3,0,0,3> wxxw, arra, qssq;
swizzle<3,0,1,0> wxyx, argr, qsts;
swizzle<3,0,1,1> wxyy, argg, qstt;
swizzle<3,0,1,2> wxyz, argb, qstp;
swizzle<3,0,1,3> wxyw, arga, qstq;
swizzle<3,0,2,0> wxzx, arbr, qsps;
swizzle<3,0,2,1> wxzy, arbg, qspt;
swizzle<3,0,2,2> wxzz, arbb, qspp;
swizzle<3,0,2,3> wxzw, arba, qspq;
swizzle<3,0,3,0> wxwx, arar, qsqs;
swizzle<3,0,3,1> wxwy, arag, qsqt;
swizzle<3,0,3,2> wxwz, arab, qsqp;
swizzle<3,0,3,3> wxww, araa, qsqq;
swizzle<3,1,0,0> wyxx, agrr, qtss;
swizzle<3,1,0,1> wyxy, agrg, qtst;
swizzle<3,1,0,2> wyxz, agrb, qtsp;
swizzle<3,1,0,3> wyxw, agra, qtsq;
swizzle<3,1,1,0> wyyx, aggr, qtts;
swizzle<3,1,1,1> wyyy, aggg, qttt;
swizzle<3,1,1,2> wyyz, aggb, qttp;
swizzle<3,1,1,3> wyyw, agga, qttq;
swizzle<3,1,2,0> wyzx, agbr, qtps;
swizzle<3,1,2,1> wyzy, agbg, qtpt;
swizzle<3,1,2,2> wyzz, agbb, qtpp;
swizzle<3,1,2,3> wyzw, agba, qtpq;
swizzle<3,1,3,0> wywx, agar, qtqs;
swizzle<3,1,3,1> wywy, agag, qtqt;
swizzle<3,1,3,2> wywz, agab, qtqp;
swizzle<3,1,3,3> wyww, agaa, qtqq;
swizzle<3,2,0,0> wzxx, abrr, qpss;
swizzle<3,2,0,1> wzxy, abrg, qpst;
swizzle<3,2,0,2> wzxz, abrb, qpsp;
swizzle<3,2,0,3> wzxw, abra, qpsq;
swizzle<3,2,1,0> wzyx, abgr, qpts;
swizzle<3,2,1,1> wzyy, abgg, qptt;
swizzle<3,2,1,2> wzyz, abgb, qptp;
swizzle<3,2,1,3> wzyw, abga, qptq;
swizzle<3,2,2,0> wzzx, abbr, qpps;
swizzle<3,2,2,1> wzzy, abbg, qppt;
swizzle<3,2,2,2> wzzz, abbb, qppp;
swizzle<3,2,2,3> wzzw, abba, qppq;
swizzle<3,2,3,0> wzwx, abar, qpqs;
swizzle<3,2,3,1> wzwy, abag, qpqt;
swizzle<3,2,3,2> wzwz, abab, qpqp;
swizzle<3,2,3,3> wzww, abaa, qpqq;
swizzle<3,3,0,0> wwxx, aarr, qqss;
swizzle<3,3,0,1> wwxy, aarg, qqst;
swizzle<3,3,0,2> wwxz, aarb, qqsp;
swizzle<3,3,0,3> wwxw, aara, qqsq;
swizzle<3,3,1,0> wwyx, aagr, qqts;
swizzle<3,3,1,1> wwyy, aagg, qqtt;
swizzle<3,3,1,2> wwyz, aagb, qqtp;
swizzle<3,3,1,3> wwyw, aaga, qqtq;
swizzle<3,3,2,0> wwzx, aabr, qqps;
swizzle<3,3,2,1> wwzy, aabg, qqpt;
swizzle<3,3,2,2> wwzz, aabb, qqpp;
swizzle<3,3,2,3> wwzw, aaba, qqpq;
swizzle<3,3,3,0> wwwx, aaar, qqqs;
swizzle<3,3,3,1> wwwy, aaag, qqqt;
swizzle<3,3,3,2> wwwz, aaab, qqqp;
swizzle<3,3,3,3> wwww, aaaa, qqqq;
};
};
}
}
#pragma GCC diagnostic pop
#endif //VECTOR_STORAGE_H

View File

@ -0,0 +1,72 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
///
/// \file vector_traits.h
/// \brief part of the \ref page_fennec_math_vector
///
///
/// \details this header implements functions to test vector types at compile time
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///
#ifndef FENNEC_MATH_VECTOR_TRAITS_H
#define FENNEC_MATH_VECTOR_TRAITS_H
#include <fennec/math/detail/__vector_traits.h>
namespace fennec
{
///
/// \brief check if \p T is a fennec::vector type
/// \tparam T type to check
template<typename T> struct is_vector : detail::__is_vector_helper<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```is_vector<T>::value```
/// \tparam T type to check
template<typename T> constexpr bool is_vector_v = is_vector<T>::value;
///
/// \brief Get the number of Components in \p T, returns 1 for types that pass ```is_arithmetic<T>```, returns \ref vector::N for \ref vector "Vector" Types, and returns 0 for all other cases
/// \tparam T type to check
template<typename T> struct component_count : detail::__component_count_helper<remove_cvr_t<T>>{};
///
/// \brief shorthand for ```component_count<T>::value```
/// \tparam T type to get the component count of
template<typename T> constexpr size_t component_count_v = component_count<T>::value;
///
/// \brief Get the total number of Components among types in \p TypesT
/// \tparam Ts types to accumulate the count of
template<typename...Ts> struct total_component_count : integral_constant<size_t, (component_count_v<Ts> + ...)>{};
///
/// \brief shorthand for ```component_count<T>::value```
/// \tparam Ts types to accumulate the count of
template<typename...Ts> constexpr size_t total_component_count_v = total_component_count<Ts...>::value;
}
#endif // FENNEC_MATH_VECTOR_TRAITS_H

View File

@ -0,0 +1,33 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_MEMORY_ALLOCATOR_H
#define FENNEC_MEMORY_ALLOCATOR_H
#include <cstdlib>
#include <memory>
namespace fennec
{
std::allocator<char> alloc;
}
#endif // FENNEC_MEMORY_ALLOCATOR_H

View File

@ -0,0 +1,51 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_MEMORY_BITS_H
#define FENNEC_MEMORY_BITS_H
#include <fennec/lang/intrinsics.h>
#include <fennec/memory/memory.h>
namespace fennec
{
///
/// \fn fennec::bit_cast(const FromT&)
/// \brief
/// \tparam ToT Type to cast to
/// \tparam FromT Type of the value
/// \param from Value to bit cast
/// \return A value containing a bitwise copy of the input
template<typename ToT, typename FromT> requires(sizeof(ToT) == sizeof(FromT))
constexpr ToT bit_cast(const FromT& from)
{
if constexpr(FENNEC_HAS_BUILTIN_BITCAST)
return __builtin_bit_cast(ToT, from);
else
{
ToT to;
memcpy(&to, &from, sizeof(ToT));
return to;
}
}
}
#endif // FENNEC_MEMORY_BITS_H

View File

@ -0,0 +1,29 @@
//
// Created by medusa on 5/19/25.
//
#ifndef FENNEC_MEMORY_DETAIL_MEMORY_H
#define FENNEC_MEMORY_DETAIL_MEMORY_H
#include <fennec/lang/types.h>
namespace fennec
{
namespace detail
{
constexpr size_t __memcpy_16(void* dst, const void* src)
{ *static_cast<uint16_t*>(dst) = *static_cast<const uint16_t*>(src); return 2; }
constexpr size_t __memcpy_32(void* dst, const void* src)
{ *static_cast<uint32_t*>(dst) = *static_cast<const uint32_t*>(src); return 4; }
constexpr size_t __memcpy_64(void* dst, const void* src)
{ *static_cast<uint64_t*>(dst) = *static_cast<const uint64_t*>(src); return 8; }
}
}
#endif // FENNEC_MEMORY_DETAIL_MEMORY_H

View File

@ -0,0 +1,150 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_MEMORY_H
#define FENNEC_MEMORY_H
#include <fennec/memory/detail/__memory.h>
namespace fennec
{
///
/// \copydetails fennec::memchr(const void*, int, size_t)
constexpr void* memchr(void* arr, int ch, size_t n)
{
uint8_t* a = static_cast<uint8_t*>(arr);
while (n--) if (*a++ == ch) return a - 1;
return nullptr;
}
///
/// \brief Finds the first occurence of ```static_cast<uint8_t>(ch)``` in the first \f$n\f$ bytes
/// \param arr Pointer to the object, interpreted as an array of bytes
/// \param ch The byte to search for
/// \param n The number of bytes to search
/// \returns A pointer to the location of \f$ch\f$, otherwise \f$nullptr\f$ if \f$ch\f$ is not found.
constexpr const void* memchr(const void* arr, int ch, size_t n)
{
const uint8_t* a = static_cast<const uint8_t*>(arr);
while (n--) if (*a++ == ch) return a - 1;
return nullptr;
}
///
/// \brief Compares the bytes of \f$lhs\f$ with \f$rhs\f$.
/// \param lhs The first object, interpreted as an array of bytes
/// \param rhs The second object, interpreted as an array of bytes
/// \param n The number of bytes to parse
/// \returns \f$0\f$ if the first \f$n\f$ bytes of \f$lhs\f$ and \f$rhs\f$ are equivalent. Otherwise returns \f$1\f$
/// for the first byte \f$b\f$ where \f$lhs[b] > \f$ rhs[b]\f$, and \f$-1\f$ for \f$
constexpr int memcmp(const void* lhs, const void* rhs, size_t n)
{
const uint8_t* lhs_ = static_cast<const uint8_t*>(lhs);
const uint8_t* rhs_ = static_cast<const uint8_t*>(rhs);
while (n--)
if (*lhs_++ != *rhs_++)
return lhs_[-1] - rhs_[-1];
return 0;
}
///
/// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$.
/// \param dst The destination object, interpreted as an array of bytes
/// \param src The source object, interpreted as an array of bytes
/// \param n The number of bytes to copy
/// \returns \f$dst\f$
///
/// \details memcpy does not do any checking for whether \f$dst\f$ and \f$src\f$ overlap. Let \f$k\f$ be the number of
/// bytes of which \f$dst\f$ and \f$src\f$. If \f$k > 0 & src < dst\f$ then the first \f$k\f$ elements of
/// \f$src\f$ will be repeated in \f$dst\f$ with a period of \f$k\f$.
///
/// A full mathematical proof of this function is possible in Set Theory.
constexpr void* memcpy(void* dst, const void* src, size_t n)
{
if (dst == src) return dst;
uint8_t* d = static_cast<uint8_t*>(dst);
const uint8_t* s = static_cast<const uint8_t*>(src);
while (n >= 8) { detail::__memcpy_64(d, s); d += 8; s += 8; n -= 8; }
while (n >= 4) { detail::__memcpy_32(d, s); d += 4; s += 4; n -= 4; }
while (n >= 2) { detail::__memcpy_16(d, s); d += 2; s += 2; n -= 2; }
while (n >= 1) { *d++ = *s++; --n; }
return dst;
}
///
/// \brief Copies the first \f$n\f$ bytes of \f$src\f$ to \f$dst\f$, with overlap correction..
/// \param dst The destination object, interpreted as an array of bytes
/// \param src The source object, interpreted as an array of bytes
/// \param n The number of bytes to copy
/// \returns \f$dst\f$
constexpr void* memmove(void* dst, const void* src, size_t n)
{
if (dst == src) return dst;
uint8_t* d = static_cast<uint8_t*>(dst);
const uint8_t* s = static_cast<const uint8_t*>(src);
if (d < s)
{
while (n >= 8) { detail::__memcpy_64(d, s); d += 8; s += 8; n -= 8; }
while (n >= 4) { detail::__memcpy_32(d, s); d += 4; s += 4; n -= 4; }
while (n >= 2) { detail::__memcpy_16(d, s); d += 2; s += 2; n -= 2; }
while (n >= 1) { *d++ = *s++; --n; }
}
else
{
d += n - 1; s += n - 1;
while (n >= 8) { detail::__memcpy_64(d, s); d -= 8; s -= 8; n -= 8; }
while (n >= 4) { detail::__memcpy_32(d, s); d -= 4; s -= 4; n -= 4; }
while (n >= 2) { detail::__memcpy_16(d, s); d -= 2; s -= 2; n -= 2; }
while (n >= 1) { *d-- = *s--; --n; }
}
return dst;
}
///
/// \brief Sets all bytes of \f$dst\f$ to \f$ch\f$, interpreted as an \f$uint8_t\f$
/// \param dst The destination object, interpreted as an array of bytes
/// \param ch The value, interpreted as an \f$uint8_t\f$
/// \param n The number of bytes to set
/// \returns \f$dst\f$
constexpr void* memset(void* dst, int ch, size_t n)
{
uint8_t* d = static_cast<uint8_t*>(dst);
uint8_t val8 = ch;
uint16_t val16 = (static_cast<uint16_t>(val8) << 8) | static_cast<int16_t>(val8);
uint32_t val32 = (static_cast<uint32_t>(val16) << 16) | static_cast<int32_t>(val16);
uint64_t val64 = (static_cast<uint64_t>(val32) << 32) | static_cast<int64_t>(val32);
while (n >= 8) { detail::__memcpy_64(d, &val64); d += 8; n -= 8; }
while (n >= 4) { detail::__memcpy_32(d, &val32); d += 4; n -= 4; }
while (n >= 2) { detail::__memcpy_16(d, &val16); d += 2; n -= 2; }
while (n >= 1) { *d++ = val8; --n; }
return dst;
}
}
#endif // FENNEC_MEMORY_H

View File

@ -0,0 +1,46 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//2
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_MEMORY_NEW_H
#define FENNEC_MEMORY_NEW_H
#include <cstdlib>
#include <new>
#include <fennec/lang/types.h>
// TODO: Document
// TODO: Memory Debugging
namespace fennec
{
///
/// \brief Alignment class to handle conflicting definitions
enum class align_t : size_t;
///
/// \brief Type to handle explicit nothrow definitions
struct nothrow_t { explicit nothrow_t() noexcept { } };
//
}
#endif // FENNEC_MEMORY_NEW_H

View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.30)
project(fennec-metaprogramming)
set(CMAKE_CXX_STANDARD 26)
add_executable(fennec-metaprogramming main.cpp)
add_custom_command(
OUTPUT .metaprogramming
COMMAND fennec-metaprogramming
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/../include/fennec/lang"
COMMENT "Generating intrinsics"
VERBATIM
)
target_link_libraries(fennec-metaprogramming PRIVATE)
add_custom_target(
metaprogramming
DEPENDS .metaprogramming
)

121
metaprogramming/main.cpp Normal file
View File

@ -0,0 +1,121 @@
// =====================================================================================================================
// fennec-metaprogramming, a program to generate metaprogramming intrinsics
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#include <fstream>
#include <math.h>
#include <cfloat>
int main(int argc, const char** argv)
{
std::ofstream flt("float.h");
flt << "// =====================================================================================================================" << std::endl;
flt << "// fennec, a free and open source game engine" << std::endl;
flt << "// Copyright © 2025 Medusa Slockbower" << std::endl;
flt << "//" << std::endl;
flt << "// This program is free software: you can redistribute it and/or modify" << std::endl;
flt << "// it under the terms of the GNU General Public License as published by" << std::endl;
flt << "// the Free Software Foundation, either version 3 of the License, or" << std::endl;
flt << "// (at your option) any later version." << std::endl;
flt << "//" << std::endl;
flt << "// This program is distributed in the hope that it will be useful," << std::endl;
flt << "// but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
flt << "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" << std::endl;
flt << "// GNU General Public License for more details." << std::endl;
flt << "//" << std::endl;
flt << "// You should have received a copy of the GNU General Public License" << std::endl;
flt << "// along with this program. If not, see <https://www.gnu.org/licenses/>." << std::endl;
flt << "// =====================================================================================================================" << std::endl;
flt << "" << std::endl;
flt << "///" << std::endl;
flt << "/// \\file float.h" << std::endl;
flt << "/// \\brief metaprogramming floating point type info" << std::endl;
flt << "///" << std::endl;
flt << "///" << std::endl;
flt << "/// \\details this file is automatically generated for the current build environment" << std::endl;
flt << "///" << std::endl;
flt << "/// \\copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << std::endl;
flt << "///" << std::endl;
flt << "///" << std::endl;
flt << "" << std::endl;
flt << "#include <fennec/memory/bits.h>" << std::endl;
flt << "" << std::endl;
flt << "#define FLT_HAS_INFINITY " << std::dec << std::numeric_limits<float>::has_infinity << std::endl;
flt << "#define FLT_HAS_QUIET_NAN " << std::dec << std::numeric_limits<float>::has_quiet_NaN << std::endl;
flt << "#define FLT_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<float>::has_signaling_NaN << std::endl;
flt << "#define FLT_HAS_DENORM " << std::dec << std::numeric_limits<float>::has_denorm << std::endl;
flt << "#define FLT_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<float>::has_denorm_loss << std::endl;
flt << "#define FLT_ROUNDS " << std::dec << std::numeric_limits<float>::round_style << std::endl;
flt << "#define FLT_IS_IEC559 " << std::dec << std::numeric_limits<float>::is_iec559 << std::endl;
flt << "#define FLT_MANT_DIG " << std::dec << std::numeric_limits<float>::digits << std::endl;
flt << "#define FLT_DIG " << std::dec << std::numeric_limits<float>::digits10 << std::endl;
flt << "#define FLT_DECIMAL_DIG " << std::dec << std::numeric_limits<float>::max_digits10 << std::endl;
flt << "#define FLT_RADIX " << std::dec << std::numeric_limits<float>::radix << std::endl;
flt << "#define FLT_MIN_EXP " << std::dec << std::numeric_limits<float>::min_exponent << std::endl;
flt << "#define FLT_MAX_EXP " << std::dec << std::numeric_limits<float>::max_exponent << std::endl;
flt << "#define FLT_MIN_10_EXP " << std::dec << std::numeric_limits<float>::min_exponent10 << std::endl;
flt << "#define FLT_MAX_10_EXP " << std::dec << std::numeric_limits<float>::max_exponent10 << std::endl;
flt << "#define FLT_TRAPS " << std::dec << std::numeric_limits<float>::traps << std::endl;
flt << "#define FLT_TINYNESS_BEFORE " << std::dec << std::numeric_limits<float>::tinyness_before << std::endl;
flt << "#define FLT_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::min() ) << ")" << std::endl;
flt << "#define FLT_MAX " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::max() ) << ")" << std::endl;
flt << "#define FLT_EPSILON " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::epsilon() ) << ")" << std::endl;
flt << "#define FLT_INF " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::infinity() ) << ")" << std::endl;
flt << "#define FLT_QUIET_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::quiet_NaN() ) << ")" << std::endl;
flt << "#define FLT_SIGNALING_NAN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::signaling_NaN()) << ")" << std::endl;
flt << "#define FLT_DENORM_MIN " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::denorm_min() ) << ")" << std::endl;
flt << "#define FLT_ROUND_ERR " << "fennec::bit_cast<float>(0x" << std::hex << std::bit_cast<int>(std::numeric_limits<float>::round_error() ) << ")" << std::endl;
flt << "" << std::endl;
flt << "#define DBL_HAS_INFINITY " << std::dec << std::numeric_limits<double>::has_infinity << std::endl;
flt << "#define DBL_HAS_QUIET_NAN " << std::dec << std::numeric_limits<double>::has_quiet_NaN << std::endl;
flt << "#define DBL_HAS_SIGNALING_NAN " << std::dec << std::numeric_limits<double>::has_signaling_NaN << std::endl;
flt << "#define DBL_HAS_DENORM " << std::dec << std::numeric_limits<double>::has_denorm << std::endl;
flt << "#define DBL_HAS_DENORM_LOSS " << std::dec << std::numeric_limits<double>::has_denorm_loss << std::endl;
flt << "#define DBL_ROUNDS " << std::dec << std::numeric_limits<double>::round_style << std::endl;
flt << "#define DBL_IS_IEC559 " << std::dec << std::numeric_limits<double>::is_iec559 << std::endl;
flt << "#define DBL_MANT_DIG " << std::dec << std::numeric_limits<double>::digits << std::endl;
flt << "#define DBL_DIG " << std::dec << std::numeric_limits<double>::digits10 << std::endl;
flt << "#define DBL_DECIMAL_DIG " << std::dec << std::numeric_limits<double>::max_digits10 << std::endl;
flt << "#define DBL_RADIX " << std::dec << std::numeric_limits<double>::radix << std::endl;
flt << "#define DBL_MIN_EXP " << std::dec << std::numeric_limits<double>::min_exponent << std::endl;
flt << "#define DBL_MAX_EXP " << std::dec << std::numeric_limits<double>::max_exponent << std::endl;
flt << "#define DBL_MIN_10_EXP " << std::dec << std::numeric_limits<double>::min_exponent10 << std::endl;
flt << "#define DBL_MAX_10_EXP " << std::dec << std::numeric_limits<double>::max_exponent10 << std::endl;
flt << "#define DBL_TRAPS " << std::dec << std::numeric_limits<double>::traps << std::endl;
flt << "#define DBL_TINYNESS_BEFORE " << std::dec << std::numeric_limits<double>::tinyness_before << std::endl;
flt << "#define DBL_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::min() ) << "l)" << std::endl;
flt << "#define DBL_MAX " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::max() ) << "l)" << std::endl;
flt << "#define DBL_EPSILON " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::epsilon() ) << "l)" << std::endl;
flt << "#define DBL_INF " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::infinity() ) << "l)" << std::endl;
flt << "#define DBL_QUIET_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::quiet_NaN() ) << "l)" << std::endl;
flt << "#define DBL_SIGNALING_NAN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::signaling_NaN()) << "l)" << std::endl;
flt << "#define DBL_DENORM_MIN " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::denorm_min() ) << "l)" << std::endl;
flt << "#define DBL_ROUND_ERR " << "fennec::bit_cast<double>(0x" << std::hex << std::bit_cast<long long>(std::numeric_limits<double>::round_error() ) << "l)" << std::endl;
flt.close();
return 0;
}

19
source/core/engine.cpp Normal file
View File

@ -0,0 +1,19 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#include <fennec/core/engine.h>

60
source/memory/new.cpp Normal file
View File

@ -0,0 +1,60 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//2
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#include <fennec/memory/new.h>
#include <cstdlib>
#ifdef FENNEC_MEMORY_DEBUGGER
#else
// Allocation functions
inline void* operator new (fennec::size_t size) { return malloc(size); }
inline void* operator new[](fennec::size_t size) { return malloc(size); }
inline void* operator new (fennec::size_t size, const fennec::nothrow_t&) { return malloc(size); }
inline void* operator new[](fennec::size_t size, const fennec::nothrow_t&) { return malloc(size); }
// Aligned allocation functions
inline void* operator new (fennec::size_t size, fennec::align_t align) { return aligned_alloc(static_cast<size_t>(align), size); }
inline void* operator new[](fennec::size_t size, fennec::align_t align) { return aligned_alloc(static_cast<size_t>(align), size); }
inline void* operator new (fennec::size_t size, fennec::align_t align, const fennec::nothrow_t&) { return aligned_alloc(static_cast<size_t>(align), size); }
inline void* operator new[](fennec::size_t size, fennec::align_t align, const fennec::nothrow_t&) { return aligned_alloc(static_cast<size_t>(align), size); }
// Deallocation functions
inline void operator delete (void* ptr) noexcept { free(ptr); }
inline void operator delete[](void* ptr) noexcept { free(ptr); }
// Aligned deallocation functions
inline void operator delete (void* ptr, fennec::align_t) noexcept { free(ptr); }
inline void operator delete[](void* ptr, fennec::align_t) noexcept { free(ptr); }
// Sized deallocation functions
inline void operator delete (void* ptr, fennec::size_t) noexcept { free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t) noexcept { free(ptr); }
inline void operator delete (void* ptr, fennec::size_t, fennec::align_t) noexcept { free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t, fennec::align_t) noexcept { free(ptr); }
// Non-throwing deallocation functions
inline void operator delete (void* ptr, const fennec::nothrow_t&) noexcept { free(ptr); }
inline void operator delete[](void* ptr, const fennec::nothrow_t&) noexcept { free(ptr); }
inline void operator delete (void* ptr, fennec::align_t, const fennec::nothrow_t&) noexcept { free(ptr); }
inline void operator delete[](void* ptr, fennec::align_t, const fennec::nothrow_t&) noexcept { free(ptr); }
inline void operator delete (void* ptr, fennec::size_t, const fennec::nothrow_t&) noexcept { free(ptr); }
inline void operator delete[](void* ptr, fennec::size_t, const fennec::nothrow_t&) noexcept { free(ptr); }
#endif

120
test.sh Executable file
View File

@ -0,0 +1,120 @@
## =====================================================================================================================
## fennec, a free and open source game engine
## Copyright © 2025 Medusa Slockbower
##
## This program is free software: 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
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <https://www.gnu.org/licenses/>.
## =====================================================================================================================
## Help ================================================================================================================
Help()
{
echo "Bash script for building fennec from source."
echo
echo "GNU long options:"
echo "--help (-h) = Print this help info."
echo "--debug (-d) = Build in debug mode, provides full debugging information to use with a debugger."
echo "--release (-r) = Build in release mode, provides full optimizations, eliminating debug info."
echo "--relwithdebinfo (-i) = Build in release mode with extra debug info, provides partial optimizations."
echo "--minsizerel (-m) = Build in release mode but optimizing for minimum binary size."
echo "--all (-a) = Build all profiles."
}
## Build Profiles ======================================================================================================
Debug()
{
mkdir -p build/debug
cd ./build/debug
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -S ../.. -B .
cmake --build . --target fennec-test
./test/fennec-test
cd ../..
}
Release()
{
mkdir -p build/release
cd ./build/release
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -S ../.. -B .
cmake --build . --target fennec-test
./test/fennec-test
cd ../..
}
RelWithDebInfo()
{
mkdir -p build/relwithdebinfo
cd ./build/relwithdebinfo
cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -S ../.. -B .
cmake --build . --target fennec-test
./test/fennec-test
cd ../..
}
MinSizeRel()
{
mkdir -p build/minsizerel
cd ./build/minsizerel
cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel -S ../.. -B .
cmake --build . --target fennec-test
./test/fennec-test
cd ../..
}
All()
{
Debug
Release
RelWithDebInfo
MinSizeRel
}
# Main Program =========================================================================================================
if [[ $# -eq 0 ]] ; then
All
exit 0
fi
while [ "${1:-}" != '' ]; do
case "$1" in
'--debug' | '-d')
Debug
exit;;
'--release' | '-r')
Release
exit;;
'--relwithdebinfo' | '-i')
RelWithDebInfo
exit;;
'--minsizerel' | '-m')
MinSizeRel
exit;;
'--all' | '-a')
All
exit;;
*)
echo "Error: Invalid option"
exit;;
esac
done

16
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.30)
project(fennec-test)
set(CMAKE_CXX_STANDARD 26)
add_executable(fennec-test main.cpp
test.h
tests/test_vector.h
tests/test_matrix.h
tests/test_scalar.h
tests/test_geometric.h
)
target_link_libraries(fennec-test PRIVATE
fennec
)

674
test/LICENSE Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
fennec-test, a free and open source game engine.
Copyright (C) 2024 Medusa Slockbower
This program is free software: 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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
fennec-test Copyright (C) 2024 Medusa Slockbower
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

68
test/main.cpp Normal file
View File

@ -0,0 +1,68 @@
// =====================================================================================================================
// fennec-test, a program to execute unit tests for fennec
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#include <iostream>
#include "tests/test_scalar.h"
#include "tests/test_vector.h"
#include "tests/test_geometric.h"
#include "tests/test_matrix.h"
#include <fennec/memory/bits.h>
int main(int, char **)
{
fennec_test_spacer(1);
fennec_test_section("fennec-test, a program to execute unit tests for fennec");
fennec_test_spacer(2);
fennec_test_section(scalar tests =================================================================================);
fennec_test_spacer(2);
fennec::test::fennec_test_scalar();
fennec_test_spacer(3);
fennec_test_section(vector tests =================================================================================);
fennec_test_spacer(2);
fennec::test::fennec_test_vector();
fennec_test_spacer(3);
fennec_test_section(geometric tests ==============================================================================);
fennec_test_spacer(2);
fennec::test::fennec_test_geometric();
fennec_test_spacer(3);
fennec_test_section(matrix tests =================================================================================);
fennec_test_spacer(2);
fennec::test::fennec_test_matrix();
return 0;
}

96
test/test.h Normal file
View File

@ -0,0 +1,96 @@
// =====================================================================================================================
// fennec-test, a program to execute unit tests for fennec
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_TEST_H
#define FENNEC_TEST_H
#include <iostream>
#include <ostream>
#include <string>
#include <cassert>
#include <fennec/lang/limits.h>
#include <fennec/math/common.h>
#include <fennec/math/relational.h>
namespace fennec
{
namespace test
{
template<typename ScalarT, size_t...IndicesV>
inline std::ostream& operator<<(std::ostream& os, const vector<ScalarT, IndicesV...>& v)
{
os << "< ";
((os << v[IndicesV] << " "), ...);
os << ">";
return os;
}
template<typename ScalarT, size_t...IndicesV>
inline std::ostream& operator<<(std::ostream& os, vector<ScalarT, IndicesV...>&& v)
{
os << "< ";
((os << v[IndicesV] << " "), ...);
os << ">";
return os;
}
template<typename ScalarT, size_t RowsV, size_t...ColIndicesV>
inline std::ostream& operator<<(std::ostream& os, const matrix<ScalarT, RowsV, ColIndicesV...>& m)
{
os << "[ ";
((os << m[ColIndicesV] << " "), ...);
os << " ]";
return os;
}
template<typename ScalarT, size_t...IndicesV>
inline bool operator<=(const vector<ScalarT, IndicesV...>& lhs, const vector<ScalarT, IndicesV...>& rhs)
{
return fennec::all(fennec::lessThanEqual(lhs, rhs));
}
template<typename ResultT>
inline void __fennec_test_run(const std::string& expression, ResultT result, ResultT expected)
{
std::cout << std::boolalpha;
std::cout << '\t' << expression << " = " << result;
bool passed = false;
if constexpr(is_arithmetic_v<ResultT> or is_vector_v<ResultT>)
passed = fennec::abs(expected - result) <= numeric_limits<ResultT>::epsilon();
else
passed = result == expected;
if (not passed)
std::cout << ", expected " << expected;
std::cout << std::endl;
assert(passed);
}
}
}
#define fennec_test_run(Expression, Expected) __fennec_test_run(#Expression, Expression, Expected)
#define fennec_test_section(Section) std::cout << #Section << std::endl
#define fennec_test_spacer(Count) std::cout << std::string(Count, std::cout.widen('\n'))
#endif // FENNEC_TEST_H

View File

@ -0,0 +1,80 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef TEST_GEOMETRIC_H
#define TEST_GEOMETRIC_H
#include <fennec/math/geometric.h>
#include <fennec/math/trigonometric.h>
#include "../test.h"
namespace fennec
{
namespace test
{
inline void fennec_test_geometric()
{
fennec_test_section(geometric functions);
fennec_test_spacer(1);
fennec_test_run(fennec::dot(vec2(1, 2), vec2(1, 2)), 5.0f);
fennec_test_run(fennec::dot(vec3(1, 2, 3), vec3(1, 2, 3)), 14.0f);
fennec_test_run(fennec::dot(vec4(1, 2, 3, 4), vec4(1, 2, 3, 4)), 30.0f);
fennec_test_spacer(1);
fennec_test_run(fennec::length2(vec2(1, 2) ), 5.0f);
fennec_test_run(fennec::length2(vec3(1, 2, 3) ), 14.0f);
fennec_test_run(fennec::length2(vec4(1, 2, 3, 4)), 30.0f);
fennec_test_spacer(1);
fennec_test_run(fennec::length(vec2(1, 2) ), sqrt(5.0f));
fennec_test_run(fennec::length(vec3(1, 2, 3) ), sqrt(14.0f));
fennec_test_run(fennec::length(vec4(1, 2, 3, 4)), sqrt(30.0f));
fennec_test_spacer(1);
fennec_test_run(fennec::distance(vec2(1, 2), vec2(2, 1)), sqrt(2.0f));
fennec_test_run(fennec::distance(vec3(1, 2, 3), vec3(3, 2, 1)), sqrt(8.0f));
fennec_test_run(fennec::distance(vec4(1, 2, 3, 4), vec4(4, 3, 2, 1)), sqrt(20.0f));
fennec_test_spacer(1);
fennec_test_run(fennec::cross(vec3(1, 0, 0), vec3(0, 1, 0)), vec3(0, 0, 1));
fennec_test_run(fennec::cross(vec3(0, 1, 0), vec3(0, 0, 1)), vec3(1, 0, 0));
fennec_test_run(fennec::cross(vec3(0, 0, 1), vec3(1, 0, 0)), vec3(0, 1, 0));
fennec_test_spacer(1);
fennec_test_run(fennec::normalize(vec2(1, 1)), vec2(sqrt(2.0f) / 2.0f, sqrt(2.0f) / 2.0f));
fennec_test_run(fennec::normalize(vec3(1, 1, 1)), vec3(sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f, sqrt(3.0f) / 3.0f));
fennec_test_run(fennec::normalize(vec4(1, 1, 1, 1)), vec4(0.5f, 0.5f, 0.5f, 0.5f));
}
}
}
#endif // TEST_GEOMETRIC_H

46
test/tests/test_matrix.h Normal file
View File

@ -0,0 +1,46 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef FENNEC_TEST_MATRIX_H
#define FENNEC_TEST_MATRIX_H
#include <fennec/math/detail/__fwd.h>
#include <fennec/math/matrix.h>
#include <iostream>
namespace fennec
{
namespace test
{
inline void fennec_test_matrix()
{
}
}
}
#endif // FENNEC_TEST_MATRIX_H

74
test/tests/test_scalar.h Normal file
View File

@ -0,0 +1,74 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright (C) 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef TEST_SCALAR_H
#define TEST_SCALAR_H
#include <fennec/math/vector_traits.h>
#include "../test.h"
namespace fennec
{
namespace test
{
inline void fennec_test_scalar()
{
fennec_test_section(component_count);
fennec_test_spacer(1);
fennec_test_run((component_count_v<bool_t> == 1), true);
fennec_test_run((component_count_v<int_t> == 1), true);
fennec_test_run((component_count_v<uint_t> == 1), true);
fennec_test_run((component_count_v<float_t> == 1), true);
fennec_test_run((component_count_v<double_t> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<const bool_t> == 1), true);
fennec_test_run((component_count_v<const int_t> == 1), true);
fennec_test_run((component_count_v<const uint_t> == 1), true);
fennec_test_run((component_count_v<const float_t> == 1), true);
fennec_test_run((component_count_v<const double_t> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<volatile bool_t> == 1), true);
fennec_test_run((component_count_v<volatile int_t> == 1), true);
fennec_test_run((component_count_v<volatile uint_t> == 1), true);
fennec_test_run((component_count_v<volatile float_t> == 1), true);
fennec_test_run((component_count_v<volatile double_t> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<const volatile bool_t> == 1), true);
fennec_test_run((component_count_v<const volatile int_t> == 1), true);
fennec_test_run((component_count_v<const volatile uint_t> == 1), true);
fennec_test_run((component_count_v<const volatile float_t> == 1), true);
fennec_test_run((component_count_v<const volatile double_t> == 1), true);
}
}
}
#endif //TEST_SCALAR_H

291
test/tests/test_vector.h Normal file
View File

@ -0,0 +1,291 @@
// =====================================================================================================================
// fennec, a free and open source game engine
// Copyright © 2025 Medusa Slockbower
//
// This program is free software: 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
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================
#ifndef TEST_VECTOR_H
#define TEST_VECTOR_H
#include <iostream>
#include <fennec/lang/types.h>
#include <fennec/math/vector.h>
#include "../test.h"
namespace fennec
{
namespace test
{
inline void fennec_test_vector()
{
fennec_test_section(component_count);
fennec_test_spacer(1);
fennec_test_run((component_count_v<bool_t&> == 1), true);
fennec_test_run((component_count_v<int_t&> == 1), true);
fennec_test_run((component_count_v<uint_t&> == 1), true);
fennec_test_run((component_count_v<float_t&> == 1), true);
fennec_test_run((component_count_v<double_t&> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<const bool_t&> == 1), true);
fennec_test_run((component_count_v<const int_t&> == 1), true);
fennec_test_run((component_count_v<const uint_t&> == 1), true);
fennec_test_run((component_count_v<const float_t&> == 1), true);
fennec_test_run((component_count_v<const double_t&> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<volatile bool_t&> == 1), true);
fennec_test_run((component_count_v<volatile int_t&> == 1), true);
fennec_test_run((component_count_v<volatile uint_t&> == 1), true);
fennec_test_run((component_count_v<volatile float_t&> == 1), true);
fennec_test_run((component_count_v<volatile double_t&> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<const volatile bool_t&> == 1), true);
fennec_test_run((component_count_v<const volatile int_t&> == 1), true);
fennec_test_run((component_count_v<const volatile uint_t&> == 1), true);
fennec_test_run((component_count_v<const volatile float_t&> == 1), true);
fennec_test_run((component_count_v<const volatile double_t&> == 1), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<bvec2> == 2), true);
fennec_test_run((component_count_v<bvec3> == 3), true);
fennec_test_run((component_count_v<bvec4> == 4), true);
fennec_test_run((component_count_v<bvec2&> == 2), true);
fennec_test_run((component_count_v<bvec3&> == 3), true);
fennec_test_run((component_count_v<bvec4&> == 4), true);
fennec_test_run((component_count_v<bvec2&&> == 2), true);
fennec_test_run((component_count_v<bvec3&&> == 3), true);
fennec_test_run((component_count_v<bvec4&&> == 4), true);
fennec_test_run((component_count_v<const bvec2&> == 2), true);
fennec_test_run((component_count_v<const bvec3&> == 3), true);
fennec_test_run((component_count_v<const bvec4&> == 4), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<ivec2> == 2), true);
fennec_test_run((component_count_v<ivec3> == 3), true);
fennec_test_run((component_count_v<ivec4> == 4), true);
fennec_test_run((component_count_v<ivec2&> == 2), true);
fennec_test_run((component_count_v<ivec3&> == 3), true);
fennec_test_run((component_count_v<ivec4&> == 4), true);
fennec_test_run((component_count_v<ivec2&&> == 2), true);
fennec_test_run((component_count_v<ivec3&&> == 3), true);
fennec_test_run((component_count_v<ivec4&&> == 4), true);
fennec_test_run((component_count_v<const ivec2&> == 2), true);
fennec_test_run((component_count_v<const ivec3&> == 3), true);
fennec_test_run((component_count_v<const ivec4&> == 4), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<uvec2> == 2), true);
fennec_test_run((component_count_v<uvec3> == 3), true);
fennec_test_run((component_count_v<uvec4> == 4), true);
fennec_test_run((component_count_v<uvec2&> == 2), true);
fennec_test_run((component_count_v<uvec3&> == 3), true);
fennec_test_run((component_count_v<uvec4&> == 4), true);
fennec_test_run((component_count_v<uvec2&&> == 2), true);
fennec_test_run((component_count_v<uvec3&&> == 3), true);
fennec_test_run((component_count_v<uvec4&&> == 4), true);
fennec_test_run((component_count_v<const uvec2&> == 2), true);
fennec_test_run((component_count_v<const uvec3&> == 3), true);
fennec_test_run((component_count_v<const uvec4&> == 4), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<vec2> == 2), true);
fennec_test_run((component_count_v<vec3> == 3), true);
fennec_test_run((component_count_v<vec4> == 4), true);
fennec_test_run((component_count_v<vec2&> == 2), true);
fennec_test_run((component_count_v<vec3&> == 3), true);
fennec_test_run((component_count_v<vec4&> == 4), true);
fennec_test_run((component_count_v<vec2&&> == 2), true);
fennec_test_run((component_count_v<vec3&&> == 3), true);
fennec_test_run((component_count_v<vec4&&> == 4), true);
fennec_test_run((component_count_v<const vec2&> == 2), true);
fennec_test_run((component_count_v<const vec3&> == 3), true);
fennec_test_run((component_count_v<const vec4&> == 4), true);
fennec_test_spacer(1);
fennec_test_run((component_count_v<dvec2> == 2), true);
fennec_test_run((component_count_v<dvec3> == 3), true);
fennec_test_run((component_count_v<dvec4> == 4), true);
fennec_test_run((component_count_v<dvec2&> == 2), true);
fennec_test_run((component_count_v<dvec3&> == 3), true);
fennec_test_run((component_count_v<dvec4&> == 4), true);
fennec_test_run((component_count_v<dvec2&&> == 2), true);
fennec_test_run((component_count_v<dvec3&&> == 3), true);
fennec_test_run((component_count_v<dvec4&&> == 4), true);
fennec_test_run((component_count_v<const dvec2&> == 2), true);
fennec_test_run((component_count_v<const dvec3&> == 3), true);
fennec_test_run((component_count_v<const dvec4&> == 4), true);
fennec_test_spacer(2);
fennec_test_section(vec2 constructors);
fennec_test_spacer(1);
fennec_test_run(vec2(), vec2(0.0f, 0.0f));
fennec_test_run(vec2(1.0f), vec2(1.0f, 1.0f));
fennec_test_run(vec2(), vec2(0.0, 0.0));
fennec_test_run(vec2(1.0), vec2(1.0, 1.0));
fennec_test_run(vec2(), vec2(0, 0));
fennec_test_run(vec2(1), vec2(1, 1));
fennec_test_run(vec2(fennec::copy(vec2(1.0f))), vec2(1.0f));
fennec_test_run(vec2(fennec::move(vec2(1.0f))), vec2(1.0f));
fennec_test_spacer(2);
fennec_test_section(vec2 swizzles);
fennec_test_spacer(1);
fennec_test_run(vec2(vec2(0, 1).xx), vec2(0, 0));
fennec_test_run(vec2(vec2(0, 1).xy), vec2(0, 1));
fennec_test_run(vec2(vec2(0, 1).yx), vec2(1, 0));
fennec_test_run(vec2(vec2(0, 1).yy), vec2(1, 1));
fennec_test_spacer(2);
fennec_test_section(vec3 constructors);
fennec_test_spacer(1);
fennec_test_run(vec3(), vec3(0.0f, 0.0f, 0.0f));
fennec_test_run(vec3(1.0f), vec3(1.0f, 1.0f, 1.0f));
fennec_test_run(vec3(), vec3(0.0, 0.0, 0.0));
fennec_test_run(vec3(1.0), vec3(1.0, 1.0, 1.0));
fennec_test_run(vec3(), vec3(0, 0, 0));
fennec_test_run(vec3(1), vec3(1, 1, 1));
fennec_test_run(vec3(fennec::copy(vec3(1))), vec3(1));
fennec_test_run(vec3(fennec::move(vec3(1))), vec3(1));
fennec_test_spacer(2);
fennec_test_section(vec3 swizzles);
fennec_test_spacer(1);
fennec_test_run(vec3(vec3(0, 1, 2).xxx), vec3(0, 0, 0));
fennec_test_run(vec3(vec3(0, 1, 2).xxy), vec3(0, 0, 1));
fennec_test_run(vec3(vec3(0, 1, 2).xxz), vec3(0, 0, 2));
fennec_test_run(vec3(vec3(0, 1, 2).xyx), vec3(0, 1, 0));
fennec_test_run(vec3(vec3(0, 1, 2).xyy), vec3(0, 1, 1));
fennec_test_run(vec3(vec3(0, 1, 2).xyz), vec3(0, 1, 2));
fennec_test_run(vec3(vec3(0, 1, 2).xzx), vec3(0, 2, 0));
fennec_test_run(vec3(vec3(0, 1, 2).xzy), vec3(0, 2, 1));
fennec_test_run(vec3(vec3(0, 1, 2).xzz), vec3(0, 2, 2));
fennec_test_spacer(1);
fennec_test_run(vec3(vec3(0, 1, 2).yxx), vec3(1, 0, 0));
fennec_test_run(vec3(vec3(0, 1, 2).yxy), vec3(1, 0, 1));
fennec_test_run(vec3(vec3(0, 1, 2).yxz), vec3(1, 0, 2));
fennec_test_run(vec3(vec3(0, 1, 2).yyx), vec3(1, 1, 0));
fennec_test_run(vec3(vec3(0, 1, 2).yyy), vec3(1, 1, 1));
fennec_test_run(vec3(vec3(0, 1, 2).yyz), vec3(1, 1, 2));
fennec_test_run(vec3(vec3(0, 1, 2).yzx), vec3(1, 2, 0));
fennec_test_run(vec3(vec3(0, 1, 2).yzy), vec3(1, 2, 1));
fennec_test_run(vec3(vec3(0, 1, 2).yzz), vec3(1, 2, 2));
fennec_test_spacer(1);
fennec_test_run(vec3(vec3(0, 1, 2).zxx), vec3(2, 0, 0));
fennec_test_run(vec3(vec3(0, 1, 2).zxy), vec3(2, 0, 1));
fennec_test_run(vec3(vec3(0, 1, 2).zxz), vec3(2, 0, 2));
fennec_test_run(vec3(vec3(0, 1, 2).zyx), vec3(2, 1, 0));
fennec_test_run(vec3(vec3(0, 1, 2).zyy), vec3(2, 1, 1));
fennec_test_run(vec3(vec3(0, 1, 2).zyz), vec3(2, 1, 2));
fennec_test_run(vec3(vec3(0, 1, 2).zzx), vec3(2, 2, 0));
fennec_test_run(vec3(vec3(0, 1, 2).zzy), vec3(2, 2, 1));
fennec_test_run(vec3(vec3(0, 1, 2).zzz), vec3(2, 2, 2));
fennec_test_spacer(2);
fennec_test_section(scalar-vector operations);
fennec_test_spacer(1);
fennec_test_run(2.0 * vec2(1, 2), vec2(2, 4));
fennec_test_run(2.0 * vec3(1, 2, 3), vec3(2, 4, 6));
fennec_test_run(2.0 * vec4(1, 2, 3, 4), vec4(2, 4, 6, 8));
fennec_test_spacer(2);
fennec_test_run(2.0 / vec2(1, 2), vec2(2.0, 1.0));
fennec_test_run(2.0 / vec3(1, 2, 4), vec3(2.0, 1.0, 0.5));
fennec_test_run(2.0 / vec4(1, 2, 4, 8), vec4(2.0, 1.0, 0.5, 0.25));
fennec_test_spacer(2);
fennec_test_section(vector-vector operations);
fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) + vec2(1, 2), vec2(2, 4));
fennec_test_run(vec3(1, 2, 3) + vec3(1, 2, 3), vec3(2, 4, 6));
fennec_test_run(vec4(1, 2, 3, 4) + vec4(1, 2, 3, 4), vec4(2, 4, 6, 8));
fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) - vec2(1, 2), vec2(0, 0));
fennec_test_run(vec3(1, 2, 3) - vec3(1, 2, 3), vec3(0, 0, 0));
fennec_test_run(vec4(1, 2, 3, 4) - vec4(1, 2, 3, 4), vec4(0, 0, 0, 0));
fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) * vec2(1, 2), vec2(1, 4));
fennec_test_run(vec3(1, 2, 3) * vec3(1, 2, 3), vec3(1, 4, 9));
fennec_test_run(vec4(1, 2, 3, 4) * vec4(1, 2, 3, 4), vec4(1, 4, 9, 16));
fennec_test_spacer(1);
fennec_test_run(vec2(1, 2) / vec2(1, 2), vec2(1, 1));
fennec_test_run(vec3(1, 2, 4) / vec3(1, 2, 4), vec3(1, 1, 1));
fennec_test_run(vec4(1, 2, 4, 8) / vec4(1, 2, 4, 8), vec4(1, 1, 1, 1));
fennec_test_spacer(1);
fennec_test_run(ivec2(1, 2) % ivec2(1, 2), ivec2(0, 0));
fennec_test_run(ivec3(1, 2, 4) % ivec3(1, 2, 4), ivec3(0, 0, 0));
fennec_test_run(ivec4(1, 2, 4, 8) % ivec4(1, 2, 4, 8), ivec4(0, 0, 0, 0));
}
}
}
#endif //TEST_VECTOR_H