*
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
@@ -0,0 +1,246 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
[Xx]64/
|
||||
[Xx]86/
|
||||
[Bb]uild/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
|
||||
# TODO: Un-comment the next line if you do not want to checkin
|
||||
# your web deploy settings because they may include unencrypted
|
||||
# passwords
|
||||
#*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Microsoft Azure ApplicationInsights config file
|
||||
ApplicationInsights.config
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
ModelManifest.xml
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
*.db
|
||||
*.filters
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
add_library(LMath INTERFACE)
|
||||
add_subdirectory(Src/LMath)
|
||||
target_include_directories(LMath INTERFACE Src)
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
# lmath
|
||||
C++ template vector math library with AMP, (SSE2, NEON and so on.. in future...) support
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
target_sources(LMath
|
||||
INTERFACE
|
||||
lmath.h
|
||||
lm_common.h
|
||||
lm_common_intrin.h
|
||||
lm_constants.h
|
||||
lm_half.h
|
||||
lm_macro.h
|
||||
lm_matrix.h
|
||||
lm_matrix_traits.h
|
||||
lm_plane.h
|
||||
lm_plane_intrin.h
|
||||
lm_quaternion.h
|
||||
lm_quaternion_intrin.h
|
||||
lm_stdio.h
|
||||
lm_traits.h
|
||||
lm_types.h
|
||||
lm_vector.h
|
||||
lm_vector_avx.h
|
||||
lm_vector_sse.h
|
||||
lm_vector_traits.h
|
||||
)
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
#ifndef lm_common_h__
|
||||
#define lm_common_h__
|
||||
|
||||
#include "lm_vector_traits.h"
|
||||
#include "lm_matrix_traits.h"
|
||||
|
||||
namespace lm{
|
||||
/*namespace common_traits {
|
||||
template<typename T, bool Valid = common_traits::is_lm_type<T>::value>
|
||||
struct field_type {
|
||||
typedef typename T::element_type type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct field_type<T, false> {
|
||||
typedef T type;
|
||||
};
|
||||
}*/
|
||||
|
||||
/*template<typename T, bool IsScalar = !common_traits::is_lm_type<T>::value>
|
||||
struct transform_copy_helper {
|
||||
template<typename OpUnary>
|
||||
static auto execute(const T& v, OpUnary op)RESTRICT(cpu) {
|
||||
typename std::remove_cv<T>::type result;
|
||||
for (LmSize i = 0; i < T::size; ++i) {
|
||||
result.data[i] = op(v.data[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#if defined(LM_AMP_SUPPORTED)
|
||||
template<typename OpUnary>
|
||||
static auto execute(const T& v, OpUnary op)RESTRICT(amp) {
|
||||
std::remove_cv<T>::type result;
|
||||
for (LmSize i = 0; i < T::size; ++i) {
|
||||
result.data[i] = op(v.data[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
};*/
|
||||
|
||||
|
||||
/*template<typename T>
|
||||
struct transform_copy_helper<T, true> {
|
||||
template<typename OpUnary>
|
||||
static auto execute(const T& v, OpUnary op) RESTRICT(cpu) {
|
||||
return op(v);
|
||||
}
|
||||
#if defined(LM_AMP_SUPPORTED)
|
||||
template<typename OpUnary>
|
||||
static auto execute(const T& v, OpUnary op) RESTRICT(amp) {
|
||||
return op(v);
|
||||
}
|
||||
#endif
|
||||
};*/
|
||||
}
|
||||
|
||||
#endif // lm_common_h__
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
#ifndef lm_common_intrin_h__
|
||||
#define lm_common_intrin_h__
|
||||
|
||||
#include "lm_vector.h"
|
||||
#include "lm_matrix.h"
|
||||
#include "lm_common.h"
|
||||
#include "lm_quaternion.h"
|
||||
#include "lm_types.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
namespace lm {
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
static inline Matrix<T, 4, 4> matrix4x4LookatLh(const Vector<T, 3>& position, const Vector<T, 3>& target, const Vector<T, 3>& up_direction) {
|
||||
auto forward = lm::normalize(target - position);
|
||||
auto right = lm::normalize(lm::cross(up_direction, forward));
|
||||
auto up = lm::normalize(lm::cross(forward, right));
|
||||
|
||||
auto zero = DefaultValues<T>::zero();
|
||||
auto one = DefaultValues<T>::one();
|
||||
|
||||
return Matrix<T, 4, 4>{
|
||||
Vector<T, 4>(right, -lm::dot(right, position)),
|
||||
Vector<T, 4>(up, -lm::dot(up, position)),
|
||||
Vector<T, 4>(forward, -lm::dot(forward, position)),
|
||||
Vector<T, 4>(zero, zero, zero, one)
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline Matrix<T, 4, 4> matrix4x4Perspective(T fov, T aspect, T near_clip, T far_clip) {
|
||||
auto zero = DefaultValues<T>::zero();
|
||||
auto one = DefaultValues<T>::one();
|
||||
auto two = DefaultValues<T>::two();
|
||||
auto yScale = one / (lm::tan(fov / two));
|
||||
return Matrix<T, 4, 4>(
|
||||
Vector<T, 4>(yScale / aspect, zero, zero, zero),
|
||||
Vector<T, 4>(zero, -yScale, zero, zero),
|
||||
Vector<T, 4>(zero, zero, far_clip / (far_clip - near_clip), (-near_clip * far_clip) / (far_clip - near_clip)),
|
||||
Vector<T, 4>(zero, zero, one, zero));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline Matrix<T, 4, 4> matrix4x4RotationY(float angleInRadians) {
|
||||
auto cosAngle = lm::cos(angleInRadians);
|
||||
auto sinAngle = lm::sin(angleInRadians);
|
||||
|
||||
auto zero = DefaultValues<T>::zero();
|
||||
auto one = DefaultValues<T>::one();
|
||||
|
||||
return Matrix<T, 4, 4>(
|
||||
Vector<T, 4>(cosAngle, zero, sinAngle, zero),
|
||||
Vector<T, 4>(zero, one, zero, zero),
|
||||
Vector<T, 4>(-sinAngle, zero, cosAngle, zero),
|
||||
Vector<T, 4>(zero, zero, zero, one));;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static inline Matrix<T, 4, 4> matrix4x4RotationQuaternion(const lm::Quaternion<T>& q) {
|
||||
auto num1 = q[0] * q[0];
|
||||
auto num2 = q[1] * q[1];
|
||||
auto num3 = q[2] * q[2];
|
||||
auto num4 = q[0] * q[1];
|
||||
auto num5 = q[2] * q[3];
|
||||
auto num6 = q[2] * q[0];
|
||||
auto num7 = q[1] * q[3];
|
||||
auto num8 = q[1] * q[2];
|
||||
auto num9 = q[0] * q[3];
|
||||
|
||||
auto zero = DefaultValues<T>::zero();
|
||||
auto one = DefaultValues<T>::one();
|
||||
auto two = DefaultValues<T>::two();
|
||||
|
||||
return Matrix<T, 4, 4>(
|
||||
Vector<T, 4>(one - two * (num2 + num3), two * (num4 - num5), two * (num6 + num7), zero),
|
||||
Vector<T, 4>(two * (num4 + num5), one - two * (num3 + num1), two * (num8 - num9), zero),
|
||||
Vector<T, 4>(two * (num6 - num7), two * (num8 + num9), one - two * (num2 + num1), zero),
|
||||
Vector<T, 4>(zero, zero, zero, one));
|
||||
}
|
||||
|
||||
template<typename T, typename U = T>
|
||||
static inline Matrix<U, 4, 4> matrix4x4Scale(T sx, T sy, T sz) {
|
||||
|
||||
auto zero = DefaultValues<T>::zero();
|
||||
auto one = DefaultValues<T>::one();
|
||||
|
||||
return Matrix<U, 4, 4>(
|
||||
Vector<U, 4>(sx, zero, zero, zero),
|
||||
Vector<U, 4>(zero, sy, zero, zero),
|
||||
Vector<U, 4>(zero, zero, sz, zero),
|
||||
Vector<U, 4>(zero, zero, zero, one));
|
||||
}
|
||||
|
||||
template<typename T, typename U = T>
|
||||
static inline Matrix<U, 4, 4> matrix4x4Scale(const Vector<T, 3>& scale) {
|
||||
return matrix4x4Scale<T, U>(scale.x(), scale.y(), scale.z());
|
||||
}
|
||||
|
||||
template<typename T, typename U = T>
|
||||
static inline Matrix<U, 4, 4> matrix4x4Translation(T x, T y, T z) {
|
||||
auto zero = DefaultValues<T>::zero();
|
||||
auto one = DefaultValues<T>::one();
|
||||
|
||||
return Matrix<U, 4, 4>(
|
||||
Vector<U, 4>(one, zero, zero, x),
|
||||
Vector<U, 4>(zero, one, zero, y),
|
||||
Vector<U, 4>(zero, zero, one, z),
|
||||
Vector<U, 4>(zero, zero, zero, one));
|
||||
}
|
||||
|
||||
template<typename T, typename U = T>
|
||||
static inline Matrix<U, 4, 4> matrix4x4Translation(const Vector<T, 3>& position) {
|
||||
return matrix4x4Translation<T, U>(position.x(), position.y(), position.z());
|
||||
}
|
||||
}
|
||||
#endif // lm_common_intrin_h__
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
#ifndef lm_constants_h__
|
||||
#define lm_constants_h__
|
||||
|
||||
namespace lm {
|
||||
static constexpr double pi_d = 3.14159265358979;
|
||||
static constexpr float pi_f = 3.14159265358979f;
|
||||
}
|
||||
#endif // lm_constants_h__
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
#ifndef LM_HALF_h__
|
||||
#define LM_HALF_h__
|
||||
|
||||
#include <cstdint>
|
||||
#include "lm_types.h"
|
||||
|
||||
namespace lm{
|
||||
|
||||
class Half{
|
||||
private:
|
||||
struct FI32{
|
||||
static_assert(sizeof(float) == 4, "Not supported float size");
|
||||
float& f() {
|
||||
return *(reinterpret_cast<float*>(&i));
|
||||
}
|
||||
uint32_t i;
|
||||
};
|
||||
std::uint16_t data;
|
||||
public:
|
||||
bool isNan() {
|
||||
return ((data & 0x7c00) == 0x7c00) && ((data & 0x3ff) != 0);
|
||||
}
|
||||
bool isInf() {
|
||||
return ((data & 0x7c00) == 0x7c00) && ((data & 0x3ff) == 0);
|
||||
}
|
||||
bool isSubnormal() {
|
||||
return ((data & 0x7c00) == 0) && ((data & 0x3ff) != 0);
|
||||
}
|
||||
bool isPositive() {
|
||||
return (data & 0x8000) == 0;
|
||||
}
|
||||
bool isZero() {
|
||||
return (data & 0x7fff) == 0;
|
||||
}
|
||||
const float toFloat() const {
|
||||
return toFloat(*this);
|
||||
}
|
||||
static Half toHalf(float src) {
|
||||
Half dst;
|
||||
FI32 fi;
|
||||
fi.f() = src;
|
||||
int32_t s,m,e;
|
||||
|
||||
//fp32 exponent zero offset = 127
|
||||
//fp16 exponent zero offset = 15
|
||||
|
||||
s = (fi.i >> 16) & 0x8000; //-V519
|
||||
m = fi.i & 0x7fffff; //-V519
|
||||
//decode exponent from fp32 and encode to fp16
|
||||
e = ((fi.i >> 23) & 0xff) - 127 + 15; //-V519
|
||||
|
||||
if ((e > 0) && (e < 30)){
|
||||
//simple case, no exp overflow, just loose precision
|
||||
dst.data = static_cast<uint16_t>((s) | (e << 10) | ((m + 0x1000) >> 13));
|
||||
}else if(src == 0.0f){
|
||||
//handle zero
|
||||
dst.data = 0;
|
||||
}else{
|
||||
//subnormal values
|
||||
if(e <= 0){
|
||||
if(e < -10){ //-10-15 = -25(exp) - too small value to represent in half float
|
||||
dst.data = 0;
|
||||
}else{//just subnormal value, representable in half
|
||||
//add explicitly 1 leading bit
|
||||
m = (m | 0x800000) >> (-e + 1);
|
||||
|
||||
//round to bigger value
|
||||
if(m & 0x1000)
|
||||
m |= 0x2000;
|
||||
dst.data = static_cast<uint16_t>((s) | (m >> 13));
|
||||
}
|
||||
}else if(e == 0xff - 127 + 15){//exp exactly on NAN or INF
|
||||
//mantissa == 0 and exp == 11111 then inf
|
||||
//else, if mantissa != 0 -> NAN
|
||||
if(m == 0){//INF
|
||||
dst.data = static_cast<uint16_t>(s | 0x7c00);
|
||||
}else{//NAN
|
||||
dst.data = static_cast<uint16_t>(s | 0x7c00 | (m >> 13));
|
||||
}
|
||||
}else{//Exp should be > 0 (> 30 or 0 + 1 (rounded))
|
||||
//round
|
||||
if(m & 0x1000){
|
||||
m += 0x2000;
|
||||
if(m & 0x800000){
|
||||
m = 0;
|
||||
e++;
|
||||
}
|
||||
}
|
||||
if(e > 30){//exp overflow
|
||||
dst.data = static_cast<uint16_t>(s | 0x7c00);//too big val, inf
|
||||
}else{//
|
||||
dst.data = static_cast<uint16_t>((s) | (e << 10) | (m >> 13));
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
static float toFloat(const Half& src) {
|
||||
int s, e, m;
|
||||
FI32 fi;
|
||||
s = src.data >> 15;
|
||||
e = (src.data & 0x7c00) >> 10;
|
||||
m = (src.data & 0x3ff);
|
||||
|
||||
if(e > 0 && e < 31){//normalized val
|
||||
fi.i = (s << 31) | ((e - 15 + 127) << 23) | (m << 13);
|
||||
}else if((e == 0) && (m == 0)){//signed zero
|
||||
fi.i = s << 31;
|
||||
}else if((e == 0) && (m != 0)){//denormalized value
|
||||
//normalize value
|
||||
while(!(m & 0x400)){
|
||||
m <<= 1;
|
||||
e--;
|
||||
}
|
||||
e++;
|
||||
m = m & 0x3ff;
|
||||
fi.i = (s << 31) | ((e - 15 + 127) << 23) | (m << 13);
|
||||
}else if((e == 31) && (m == 0)){//INF
|
||||
fi.i = (s << 31) | 0x7f800000;
|
||||
}else{
|
||||
fi.i = (s << 31) | 0x7f800000 | (m << 13);
|
||||
}
|
||||
return fi.f();
|
||||
}
|
||||
|
||||
Half() {
|
||||
|
||||
}
|
||||
Half(const Half& val) {
|
||||
data = val.data;
|
||||
}
|
||||
Half(const float& val) {
|
||||
*this = toHalf(val);
|
||||
}
|
||||
Half& operator =(const float& other) {
|
||||
*this = toHalf(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//operators
|
||||
Half operator +() {
|
||||
return *this;
|
||||
}
|
||||
Half operator -() {
|
||||
return toHalf(-toFloat());
|
||||
}
|
||||
Half operator +(const Half& rval) {
|
||||
return toHalf(this->toFloat() + rval.toFloat());
|
||||
}
|
||||
Half operator -(const Half& rval) {
|
||||
return toHalf(this->toFloat() - rval.toFloat());
|
||||
}
|
||||
Half operator *(const Half& rval) {
|
||||
return toHalf(this->toFloat() * rval.toFloat());
|
||||
}
|
||||
Half operator /(const Half& rval) {
|
||||
return toHalf(this->toFloat() / rval.toFloat());
|
||||
}
|
||||
|
||||
bool operator ==(const Half& rval) {
|
||||
return data == rval.data;
|
||||
}
|
||||
bool operator !=(const Half& rval) {
|
||||
return data != rval.data;
|
||||
}
|
||||
bool operator <(const Half& rval) {
|
||||
return this->toFloat() < rval.toFloat();
|
||||
}
|
||||
bool operator >(const Half& rval) {
|
||||
return this->toFloat() > rval.toFloat();
|
||||
}
|
||||
bool operator <=(const Half& rval) {
|
||||
return this->toFloat() <= rval.toFloat();
|
||||
}
|
||||
bool operator >=(const Half& rval) {
|
||||
return this->toFloat() >= rval.toFloat();
|
||||
}
|
||||
Half& operator +=(const Half& rval) {
|
||||
*this = toHalf(this->toFloat() + rval.toFloat());
|
||||
return *this;
|
||||
}
|
||||
Half& operator -=(const Half& rval) {
|
||||
*this = toHalf(this->toFloat() - rval.toFloat());
|
||||
return *this;
|
||||
}
|
||||
Half& operator *=(const Half& rval) {
|
||||
*this = toHalf(this->toFloat() * rval.toFloat());
|
||||
return *this;
|
||||
}
|
||||
Half& operator /=(const Half& rval) {
|
||||
*this = toHalf(this->toFloat() / rval.toFloat());
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Half& operator++() {
|
||||
*this = toHalf(this->toFloat() + 1.0f);
|
||||
return *this;
|
||||
}
|
||||
const Half operator++(int) {
|
||||
Half old(*this);
|
||||
*this = toHalf(this->toFloat() + 1.0f);
|
||||
return old;
|
||||
}
|
||||
const Half& operator--() {
|
||||
*this = toHalf(this->toFloat() - 1.0f);
|
||||
return *this;
|
||||
}
|
||||
const Half operator--(int) {
|
||||
Half old(*this);
|
||||
*this = toHalf(this->toFloat() - 1.0f);
|
||||
return old;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Half half;
|
||||
}
|
||||
#endif // LM_HALF_h__
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
#ifndef lm_macro_h__
|
||||
#define lm_macro_h__
|
||||
|
||||
#define EMPTY_SUFFIX
|
||||
#define UNPACK(...) __VA_ARGS__
|
||||
#define GEN_METHOD(_Method) _Method(EMPTY_SUFFIX) ENABLE_IF_AMP( _Method(restrict(amp)) )
|
||||
|
||||
#define GEN_METHOD_CONST(_Method) _Method(const) ENABLE_IF_AMP( _Method(const restrict(amp)) )
|
||||
|
||||
#define GEN_METHOD2(_Method) _Method(EMPTY_SUFFIX, EMPTY_SUFFIX) _Method(const, const) ENABLE_IF_AMP( _Method(EMPTY_SUFFIX, restrict(amp)) _Method(const, const restrict(amp)) )
|
||||
|
||||
#define GEN_METHOD_PARAMS(_Method, ...) UNPACK(_Method(__VA_ARGS__, EMPTY_SUFFIX)) UNPACK( ENABLE_IF_AMP( _Method(__VA_ARGS__, restrict(amp)) ))
|
||||
|
||||
#endif // lm_macro_h__
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
#ifndef lm_matrix_h__
|
||||
#define lm_matrix_h__
|
||||
|
||||
#include "lm_vector.h"
|
||||
#include "lm_types.h"
|
||||
#include <array>
|
||||
#include "lm_matrix_traits.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace lm {
|
||||
template<typename T, LmSize M, LmSize N>
|
||||
struct Matrix : public Vector<Vector<T, N>, M> {
|
||||
typedef Vector<T, N> Row;
|
||||
typedef Vector<Vector<T, N>, M> Base;
|
||||
|
||||
template<typename ... Args, typename = std::enable_if_t<sizeof...(Args) <= M>>
|
||||
Matrix(const Args& ... rest) RESTRICT(cpu) : Base{ rest... } {}
|
||||
|
||||
constexpr Matrix() RESTRICT(cpu, amp) {}
|
||||
|
||||
Matrix(const Matrix& m) RESTRICT(cpu, amp) : Base{ (const Base&)m } {}
|
||||
|
||||
Matrix(const Vector<Vector<T, N>, M>& m) RESTRICT(cpu, amp) : Base{ m } {}
|
||||
|
||||
auto getColumn(LmSize id) const RESTRICT(cpu, amp) {
|
||||
Vector<T, M> result;
|
||||
for (LmSize i = 0; i < M; ++i) {
|
||||
result[i] = this->get(i)[id];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static Matrix identity() RESTRICT(cpu, amp) {
|
||||
auto zero = DefaultValues<T>::zero();
|
||||
Matrix result(zero);
|
||||
for (LmSize y = 0; y < M; ++y) {
|
||||
result[y][y] = static_cast<T>(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T2, LmSize M2, LmSize N2, typename = typename std::enable_if_t<(M2 <= M) && (N2 <= N)>>
|
||||
operator Matrix<T2, M2, N2>() const RESTRICT(cpu, amp) {
|
||||
Matrix<T2, M2, N2> result;
|
||||
for (LmSize y = 0; y < M2; ++y){
|
||||
for (LmSize x = 0; x < N2; ++x) {
|
||||
result[y][x] = this->data[y][x];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1, typename T2, LmSize M, LmSize N, LmSize N2>
|
||||
auto mul(const Matrix<T1, M, N>& left, const Matrix<T2, N, N2>& right) RESTRICT(cpu, amp) {
|
||||
auto result = Matrix<MultiplyType<T1, T2>, M, N2>{};
|
||||
for (LmSize y = 0; y < M; ++y) {
|
||||
for (LmSize x = 0; x < N2; ++x) {
|
||||
|
||||
result[y][x] = DefaultValues<std::remove_reference_t<decltype(result[y][x])>>::zero();
|
||||
|
||||
for (LmSize i = 0; i < N; ++i) {
|
||||
result[y][x] += left[y][i] * right[i][x];
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename TM, typename TV, LmSize M, LmSize N>
|
||||
auto mul(const Matrix<TM, M, N>& left, const Vector<TV, N>& right) RESTRICT(cpu, amp) {
|
||||
auto result = Vector<MultiplyType<TM, TV>, N>{};
|
||||
for (LmSize y = 0; y < M; ++y) {
|
||||
result[y] = dot(left[y], right);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T, LmSize M, LmSize N, typename = std::enable_if_t<(M == N) && (M == 2)>>
|
||||
auto determinant(const Matrix<T, M, N>& m) RESTRICT(cpu, amp) {
|
||||
return m[0][0] * m[1][1] - m[0][1] * m[1][0];
|
||||
}
|
||||
|
||||
|
||||
template<typename T, LmSize M, LmSize N, typename = std::enable_if_t<(M == N) && ((M == 3) || (M == 4))>>
|
||||
auto determinantAffine(const Matrix<T, M, N>& m) RESTRICT(cpu, amp) {
|
||||
return
|
||||
(m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[0][1] * m[1][2] * m[2][0]) -
|
||||
(m[0][2] * m[1][1] * m[2][0] + m[0][1] * m[1][0] * m[2][2] + m[1][2] * m[2][1] * m[0][0]);
|
||||
}
|
||||
|
||||
template<typename T, LmSize M, LmSize N>
|
||||
Matrix<T, N, M> transpose(const Matrix<T, M, N>& v) RESTRICT(cpu, amp) {
|
||||
Matrix<T, N, M> result;
|
||||
|
||||
for (LmSize y = 0; y < M; ++y) {
|
||||
for (LmSize x = 0; x < N; ++x) {
|
||||
result[x][y] = v[y][x];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
Matrix<T, 4, 4> inverse(const Matrix<T, 4, 4>& u, bool affine) RESTRICT(cpu, amp) {
|
||||
Matrix<T, 4, 4> result;
|
||||
if (affine) {
|
||||
T s = static_cast<T>(1) / determinantAffine(u);
|
||||
result[0][0] = (u[1][1] * u[2][2] - u[1][2] * u[2][1]) * s;
|
||||
result[0][1] = (u[2][1] * u[0][2] - u[2][2] * u[0][1]) * s;
|
||||
result[0][2] = (u[0][1] * u[1][2] - u[0][2] * u[1][1]) * s;
|
||||
result[0][3] = u[0][3];
|
||||
result[1][0] = (u[1][2] * u[2][0] - u[1][0] * u[2][2]) * s;
|
||||
result[1][1] = (u[2][2] * u[0][0] - u[2][0] * u[0][2]) * s;
|
||||
result[1][2] = (u[0][2] * u[1][0] - u[0][0] * u[1][2]) * s;
|
||||
result[1][3] = u[1][3];
|
||||
result[2][0] = (u[1][0] * u[2][1] - u[1][1] * u[2][0]) * s;
|
||||
result[2][1] = (u[2][0] * u[0][1] - u[2][1] * u[0][0]) * s;
|
||||
result[2][2] = (u[0][0] * u[1][1] - u[0][1] * u[1][0]) * s;
|
||||
result[2][3] = u[2][3];
|
||||
result[3][0] = -(result[0][0] * u[3][0] + result[1][0] * u[3][1] + result[2][0] * u[3][2]);
|
||||
result[3][1] = -(result[0][1] * u[3][0] + result[1][1] * u[3][1] + result[2][1] * u[3][2]);
|
||||
result[3][2] = -(result[0][2] * u[3][0] + result[1][2] * u[3][1] + result[2][2] * u[3][2]);
|
||||
result[3][3] = u[3][3];
|
||||
}
|
||||
else {
|
||||
|
||||
// transpose matrix
|
||||
T src[16];
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
src[i] = u[i][0];
|
||||
src[i + 4] = u[i][1];
|
||||
src[i + 8] = u[i][2];
|
||||
src[i + 12] = u[i][3];
|
||||
}
|
||||
|
||||
// calculate pairs for first 8 elements (cofactors)
|
||||
T tmp[12]; // temp array for pairs
|
||||
tmp[0] = src[10] * src[15];
|
||||
tmp[1] = src[11] * src[14];
|
||||
tmp[2] = src[9] * src[15];
|
||||
tmp[3] = src[11] * src[13];
|
||||
tmp[4] = src[9] * src[14];
|
||||
tmp[5] = src[10] * src[13];
|
||||
tmp[6] = src[8] * src[15];
|
||||
tmp[7] = src[11] * src[12];
|
||||
tmp[8] = src[8] * src[14];
|
||||
tmp[9] = src[10] * src[12];
|
||||
tmp[10] = src[8] * src[13];
|
||||
tmp[11] = src[9] * src[12];
|
||||
|
||||
// calculate first 8 elements (cofactors)
|
||||
result[0][0] = (tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7]) - (tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7]);
|
||||
result[0][1] = (tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7]) - (tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7]);
|
||||
result[0][2] = (tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7]) - (tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7]);
|
||||
result[0][3] = (tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6]) - (tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6]);
|
||||
result[1][0] = (tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3]) - (tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3]);
|
||||
result[1][1] = (tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3]) - (tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3]);
|
||||
result[1][2] = (tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3]) - (tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3]);
|
||||
result[1][3] = (tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2]) - (tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2]);
|
||||
|
||||
// calculate pairs for second 8 elements (cofactors)
|
||||
tmp[0] = src[2] * src[7];
|
||||
tmp[1] = src[3] * src[6];
|
||||
tmp[2] = src[1] * src[7];
|
||||
tmp[3] = src[3] * src[5];
|
||||
tmp[4] = src[1] * src[6];
|
||||
tmp[5] = src[2] * src[5];
|
||||
tmp[6] = src[0] * src[7];
|
||||
tmp[7] = src[3] * src[4];
|
||||
tmp[8] = src[0] * src[6];
|
||||
tmp[9] = src[2] * src[4];
|
||||
tmp[10] = src[0] * src[5];
|
||||
tmp[11] = src[1] * src[4];
|
||||
|
||||
// calculate second 8 elements (cofactors)
|
||||
result[2][0] = (tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15]) - (tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15]);
|
||||
result[2][1] = (tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15]) - (tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15]);
|
||||
result[2][2] = (tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15]) - (tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15]);
|
||||
result[2][3] = (tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14]) - (tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14]);
|
||||
result[3][0] = (tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9]) - (tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10]);
|
||||
result[3][1] = (tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10]) - (tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8]);
|
||||
result[3][2] = (tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8]) - (tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9]);
|
||||
result[3][3] = (tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9]) - (tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8]);
|
||||
|
||||
// calculate determinant
|
||||
T det = src[0] * result[0][0] + src[1] * result[0][1] + src[2] * result[0][2] + src[3] * result[0][3];
|
||||
|
||||
// calculate matrix inverse
|
||||
det = static_cast<T>(1) / det;
|
||||
|
||||
for (LmSize i = 0; i < 4; ++i) {
|
||||
for (LmSize j = 0; j < 4; ++j) {
|
||||
result[i][j] *= det;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef Matrix<float, 2, 2> float2x2;
|
||||
typedef Matrix<float, 2, 3> float2x3;
|
||||
typedef Matrix<float, 3, 3> float3x3;
|
||||
typedef Matrix<float, 3, 4> float3x4;
|
||||
typedef Matrix<float, 4, 3> float4x3;
|
||||
typedef Matrix<float, 4, 4> float4x4;
|
||||
typedef Matrix<double, 2, 2> double2x2;
|
||||
typedef Matrix<double, 2, 3> double2x3;
|
||||
typedef Matrix<double, 3, 3> double3x3;
|
||||
typedef Matrix<double, 3, 4> double3x4;
|
||||
typedef Matrix<double, 4, 3> double4x3;
|
||||
typedef Matrix<double, 4, 4> double4x4;
|
||||
}
|
||||
#endif // lm_matrix_h__
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
#ifndef lm_matrix_traits_h__
|
||||
#define lm_matrix_traits_h__
|
||||
|
||||
#include "lm_vector_traits.h"
|
||||
#include "lm_types.h"
|
||||
|
||||
namespace lm{
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct MatrixSize {
|
||||
static constexpr size_t rows = VectorSize<T>::value;
|
||||
static constexpr size_t columns = VectorSize<typename T::ElementType>::value;
|
||||
static constexpr auto value = lm::Vector<lm::LmSize, 2>(rows, columns);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MatrixRowType {
|
||||
typedef typename T::ElementType type;
|
||||
};
|
||||
|
||||
template<typename T, bool IsVector>
|
||||
struct MatrixColumnType_ {
|
||||
typedef Vector<typename T::ElementType, T::Size> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MatrixColumnType_<T, true> {
|
||||
typedef Vector<typename T::ElementType::ElementType, T::Size> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MatrixColumnType : MatrixColumnType_<T, IsVector<typename T::ElementType>::value> {
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct IsSquare {
|
||||
static constexpr bool Value = MatrixSize<T>::rows == MatrixSize<T>::columns;
|
||||
};
|
||||
|
||||
template<typename Left, typename Right>
|
||||
struct CanMultiplyMatrix {
|
||||
static constexpr bool Value = MatrixSize<Left>::columns == MatrixSize<Right>::rows;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Left, typename Right>
|
||||
using DotResultType = MultiplyType<decltype(std::declval<Left>()[0]), decltype(std::declval<Right>()[0])>;
|
||||
|
||||
}
|
||||
|
||||
#endif // lm_matrix_traits_h__
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#ifndef lm_plane_h__
|
||||
#define lm_plane_h__
|
||||
|
||||
#include "lm_vector.h"
|
||||
|
||||
namespace lm
|
||||
{
|
||||
template<typename T>
|
||||
struct Plane {
|
||||
union{
|
||||
T data[4];
|
||||
struct
|
||||
{
|
||||
lm::Vector<T, 3> normal;
|
||||
T d;
|
||||
};
|
||||
};
|
||||
|
||||
Plane() : normal(0,1,0), d(0) {}
|
||||
|
||||
Plane(T _a, T _b, T _c, T _d) : normal(_a,_b,_c), d(_d) {}
|
||||
|
||||
Plane(Vector<T,3>& _normal, float _d) : normal(_normal), d(_d) {}
|
||||
|
||||
Plane& operator=(const Plane& v) {
|
||||
normal = v.normal;
|
||||
d = v.d;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // lm_plane_h__
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
#ifndef lm_plane_intrin_h__
|
||||
#define lm_plane_intrin_h__
|
||||
|
||||
#include "lm_plane.h"
|
||||
|
||||
namespace lm
|
||||
{
|
||||
template<typename T, typename U>
|
||||
static inline auto dot(const Plane<T>& plane, const Vector<U, 4>& value) {
|
||||
return ((((plane.normal.x() * value.x()) + (plane.normal.y() * value.y())) + (plane.normal.z() * value.z())) + (plane.d * value.w()));
|
||||
}
|
||||
|
||||
/*static inline float PlaneDot(const Plane& plane, const Vector4D& value) {
|
||||
return ((((plane.Normal.X * value.X) + (plane.Normal.Y * value.Y)) + (plane.Normal.Z * value.Z)) + (plane.D * value.W));
|
||||
}
|
||||
static inline float PlaneDotCoordinate(const Plane& plane, const Vector3D& value) {
|
||||
return ((((plane.Normal.X * value.X) + (plane.Normal.Y * value.Y)) + (plane.Normal.Z * value.Z)) + plane.D);
|
||||
}
|
||||
|
||||
static inline float PlaneDotNormal(const Plane& plane, const Vector3D& value) {
|
||||
return (((plane.Normal.X * value.X) + (plane.Normal.Y * value.Y)) + (plane.Normal.Z * value.Z));
|
||||
}
|
||||
static inline float PlaneDot(const Plane& plane, const Vector3D& point) {
|
||||
return ((((plane.Normal.Y * point.Y) + (plane.Normal.X * point.X)) + (plane.Normal.Z * point.Z)) + plane.D);
|
||||
}*/
|
||||
|
||||
|
||||
/*static inline float PlaneDotCoordinate(const Plane& plane, const Vector3D& value) {
|
||||
return ((((plane.Normal.X * value.X) + (plane.Normal.Y * value.Y)) + (plane.Normal.Z * value.Z)) + plane.D);
|
||||
}
|
||||
static inline float PlaneDotNormal(const Plane& plane, const Vector3D& value) {
|
||||
return (((plane.Normal.X * value.X) + (plane.Normal.Y * value.Y)) + (plane.Normal.Z * value.Z));
|
||||
}*/
|
||||
template<typename T, typename U>
|
||||
static inline auto dot(const Plane<T>& plane, const Vector<U, 3>& point) {
|
||||
return ((((plane.normal.y * point.y) + (plane.normal.x * point.x)) + (plane.normal.z * point.z)) + plane.D);
|
||||
}
|
||||
}
|
||||
#endif // lm_plane_intrin_h__
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
#ifndef lm_quaternion_h__
|
||||
#define lm_quaternion_h__
|
||||
|
||||
#include "lm_vector.h"
|
||||
|
||||
namespace lm {
|
||||
template<typename T>
|
||||
struct Quaternion {
|
||||
T data[4];
|
||||
|
||||
constexpr Quaternion() {}
|
||||
|
||||
constexpr Quaternion(T x, T y, T z, T w) : data{ x,y,z,w } {}
|
||||
|
||||
static Quaternion angleAxis(T angleRadians, const Vector<T, 3>& axis) {
|
||||
auto theta = angleRadians / DefaultValues<T>::two();
|
||||
auto s = lm::sin(theta);
|
||||
auto c = lm::cos(theta);
|
||||
|
||||
return Quaternion(
|
||||
axis[0] * s,
|
||||
axis[1] * s,
|
||||
axis[2] * s, c);
|
||||
}
|
||||
|
||||
T& x() { return data[0]; }
|
||||
const T& x() const { return data[0]; }
|
||||
|
||||
T& y() { return data[1]; }
|
||||
const T& y() const { return data[1]; }
|
||||
|
||||
T& z() { return data[2]; }
|
||||
const T& z() const { return data[2]; }
|
||||
|
||||
T& w() { return data[3]; }
|
||||
const T& w() const { return data[3]; }
|
||||
|
||||
static Quaternion identity() {
|
||||
auto zero = DefaultValues<T>::zero();
|
||||
auto one = DefaultValues<T>::one();
|
||||
return Quaternion(zero, zero, zero, one);
|
||||
}
|
||||
|
||||
T normSquare() const{
|
||||
return data[0] * data[0] + data[1] * data[1] + data[2] * data[2] + data[3] * data[3];
|
||||
}
|
||||
|
||||
T norm() const {
|
||||
return lm::sqrt(normSquare());
|
||||
}
|
||||
|
||||
|
||||
void conjugate() const {
|
||||
for (LmSize i = 0; i < 3; ++i) {
|
||||
data[i] = -data[i];
|
||||
}
|
||||
}
|
||||
void inverse() {
|
||||
auto n = static_cast<T>(-1) / normSquare();
|
||||
data[0] = data[0] * n;
|
||||
data[1] = data[1] * n;
|
||||
data[2] = data[2] * n;
|
||||
data[3] = data[3] * -n;
|
||||
}
|
||||
|
||||
|
||||
Quaternion operator -() const {
|
||||
return Quaternion(-data[0], -data[1], -data[2], data[3]);
|
||||
}
|
||||
|
||||
bool operator==(const Quaternion& a) const{
|
||||
return
|
||||
data[0] == a.data[0] &&
|
||||
data[1] == a.data[1] &&
|
||||
data[2] == a.data[2] &&
|
||||
data[3] == a.data[3];
|
||||
}
|
||||
|
||||
bool operator!=(const Quaternion& a) const {
|
||||
return
|
||||
data[0] != a.data[0] ||
|
||||
data[1] != a.data[1] ||
|
||||
data[2] != a.data[2] ||
|
||||
data[3] != a.data[3];
|
||||
}
|
||||
|
||||
|
||||
Quaternion operator *(const Quaternion& r) const {
|
||||
Quaternion result;
|
||||
result[3] = r[3] * data[3] - r[0] * data[0] - r[1] * data[1] - r[2] * data[2];
|
||||
result[0] = r[3] * data[0] + r[0] * data[3] - r[1] * data[2] + r[2] * data[1];
|
||||
result[1] = r[3] * data[1] + r[0] * data[2] + r[1] * data[3] - r[2] * data[0];
|
||||
result[2] = r[3] * data[2] - r[0] * data[1] + r[1] * data[0] + r[2] * data[3];
|
||||
return result;
|
||||
}
|
||||
|
||||
T& operator[](LmSize id) {
|
||||
return data[id];
|
||||
}
|
||||
const T& operator[](LmSize id) const {
|
||||
return data[id];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline auto dot(const Quaternion<T>& a, const Quaternion<T>& b) {
|
||||
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline Quaternion<T> lerp(const Quaternion<T>& a, const Quaternion<T>& b, const T& x) {
|
||||
return Quaternion<T>(
|
||||
a[0] + (b[0] - a[0]) * x,
|
||||
a[1] + (b[1] - a[1]) * x,
|
||||
a[2] + (b[2] - a[2]) * x,
|
||||
a[3] + (b[3] - a[3]) * x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Quaternion<T> slerp(const Quaternion<T>& a, const Quaternion<T>& b, const T& x) {
|
||||
auto cosom = dot(a, b);
|
||||
|
||||
if ((DefaultValues<T>::one() + cosom) > std::numeric_limits<T>::epsilon()) {
|
||||
T sp;
|
||||
T sq;
|
||||
if ((DefaultValues<T>::one() - cosom) > std::numeric_limits<T>::epsilon()) {
|
||||
double omega = lm::acos(cosom);
|
||||
double sinom = DefaultValues<T>::one() / lm::sin(omega);
|
||||
|
||||
sp = static_cast<T>(sin((DefaultValues<T>::one() - x) * omega) * sinom);
|
||||
sq = static_cast<T>(sin(x * omega) * sinom);
|
||||
}
|
||||
else {
|
||||
sp = DefaultValues<T>::one() - x;
|
||||
sq = x;
|
||||
}
|
||||
return Quaternion<T>(
|
||||
a[0] * sp + b[0] * sq,
|
||||
a[1] * sp + b[1] * sq,
|
||||
a[2] * sp + b[2] * sq,
|
||||
a[3] * sp + b[3] * sq);
|
||||
}
|
||||
else {
|
||||
auto halfpi = static_cast<T>(lm::pi_d / DefaultValues<T>::two()); //TODO: cleanup types mess
|
||||
auto sp = static_cast<T>(lm::sin((DefaultValues<T>::one() - x) * halfpi));
|
||||
auto sq = static_cast<T>(lm::sin(x * halfpi));
|
||||
return Quaternion<T>(
|
||||
a[0] * sp - a[1] * sq,
|
||||
a[1] * sp + a[0] * sq,
|
||||
a[2] * sp - a[3] * sq,
|
||||
a[2]);
|
||||
}
|
||||
}
|
||||
|
||||
typedef Quaternion<float> Quaternion_f;
|
||||
}
|
||||
#endif // lm_quaternion_h__
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef lm_quaternion_intrin_h__
|
||||
#define lm_quaternion_intrin_h__
|
||||
|
||||
#include "lm_quaternion.h"
|
||||
|
||||
namespace lm
|
||||
{
|
||||
template<typename Q1, typename Q2>
|
||||
auto mul(const lm::Quaternion<Q1>& q1, const lm::Quaternion<Q2>& q2) {
|
||||
return lm::Quaternion<decltype(q1.x() * q2.x())>(
|
||||
(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y()),
|
||||
(q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z()),
|
||||
(q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x()),
|
||||
(q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z())
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif // lm_quaternion_intrin_h__
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#ifndef lm_stdio_h__
|
||||
#define lm_stdio_h__
|
||||
|
||||
#include <ostream>
|
||||
#include "lm_vector.h"
|
||||
|
||||
namespace lm
|
||||
{
|
||||
template<typename T, size_t N>
|
||||
std::ostream& operator<<(std::ostream& os, const Vector<T, N>& obj) {
|
||||
os << "[";
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
os << obj.data[i];
|
||||
if(i != (N - 1))
|
||||
{
|
||||
os << ", ";
|
||||
}
|
||||
}
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // lm_stdio_h__
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
#ifndef lm_traits_h__
|
||||
#define lm_traits_h__
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace lm {
|
||||
template<typename A, typename B = A>
|
||||
using MultiplyType = decltype(A() * B());
|
||||
|
||||
template<typename A, typename B = A>
|
||||
using DivideType = decltype(A() / B());
|
||||
}
|
||||
|
||||
#endif // lm_traits_h__
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#ifndef lm_types_h__
|
||||
#define lm_types_h__
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
//#define LM_AMP_SUPPORTED
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(LM_AMP_SUPPORTED)
|
||||
#include <amp.h>
|
||||
#include <amp_math.h>
|
||||
#endif
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace lm {
|
||||
#if defined(LM_AMP_SUPPORTED)
|
||||
#define RESTRICT(...) restrict(__VA_ARGS__)
|
||||
#define ENABLE_IF_AMP(...) __VA_ARGS__
|
||||
#else
|
||||
#define RESTRICT(...)
|
||||
#define ENABLE_IF_AMP(...)
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
struct DefaultValues {
|
||||
static T zero() RESTRICT(cpu, amp) {
|
||||
return static_cast<T>(0);
|
||||
}
|
||||
static T one() RESTRICT(cpu, amp) {
|
||||
return static_cast<T>(1);
|
||||
}
|
||||
static T two() RESTRICT(cpu, amp) {
|
||||
return static_cast<T>(2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
T zero = static_cast<T>(0);
|
||||
template<typename T>
|
||||
T one = static_cast<T>(1);
|
||||
template<typename T>
|
||||
T two = static_cast<T>(2);
|
||||
|
||||
typedef size_t LmSize;
|
||||
}
|
||||
|
||||
#endif // lm_types_h__
|
||||
+711
@@ -0,0 +1,711 @@
|
||||
#ifndef lm_vector_h__
|
||||
#define lm_vector_h__
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "lm_types.h"
|
||||
#include "lm_constants.h"
|
||||
#include "lm_macro.h"
|
||||
#include "lm_traits.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace lm {
|
||||
|
||||
#define LM_VECTOR_ARITHMETIC_OP_SCALAR(_Op, _Suffix) \
|
||||
template<typename T, LmSize N, InstructionSet Instructions, typename U> \
|
||||
auto operator _Op (const Vector<T, N, Instructions>& l, const U& divider) _Suffix { \
|
||||
Vector<DivideType<T, U>, N, Instructions> result; \
|
||||
for (LmSize i = 0; i < N; ++i) { \
|
||||
result.set(i, l.get(i) _Op divider); \
|
||||
} \
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define LM_VECTOR_ARITHMETIC_OP_VECTOR(_Op, _Suffix) \
|
||||
template<typename T, LmSize N, InstructionSet Instructions, typename U> \
|
||||
auto operator _Op (const Vector<T, N, Instructions>& l, Vector<U, N, Instructions> divider) _Suffix {\
|
||||
Vector<DivideType<T, U>, N, Instructions> result; \
|
||||
for (LmSize i = 0; i < N; ++i) {\
|
||||
result.set(i, l.get(i) _Op divider.get(i)); \
|
||||
} \
|
||||
return result; \
|
||||
} \
|
||||
|
||||
#define LM_VECTOR_ARITHMETIC_OP_SELF_SCALAR(_Op, _Suffix) \
|
||||
template<typename T, LmSize N, InstructionSet Instructions, typename U>\
|
||||
auto operator _Op## = (Vector<T, N, Instructions>& l, const U& divider) _Suffix { \
|
||||
for (LmSize i = 0; i < N; ++i) { \
|
||||
l.set(i, l.get(i) _Op divider); \
|
||||
} \
|
||||
return l; \
|
||||
}
|
||||
|
||||
#define LM_VECTOR_ARITHMETIC_OP_SELF_VECTOR(_Op, _Suffix) \
|
||||
template<typename T, LmSize N, InstructionSet Instructions, typename U> \
|
||||
auto operator _Op##= (Vector<T, N, Instructions>& l, Vector<U, N, Instructions> divider) _Suffix{ \
|
||||
for (LmSize i = 0; i < N; ++i) { \
|
||||
l.set(i, l.get(i) _Op divider.get(i)); \
|
||||
} \
|
||||
return l; \
|
||||
}
|
||||
|
||||
#define LM_VECTOR_ARITHMETIC_OP(_Op) \
|
||||
GEN_METHOD_PARAMS(LM_VECTOR_ARITHMETIC_OP_SCALAR, _Op) \
|
||||
GEN_METHOD_PARAMS(LM_VECTOR_ARITHMETIC_OP_VECTOR, _Op) \
|
||||
GEN_METHOD_PARAMS(LM_VECTOR_ARITHMETIC_OP_SELF_SCALAR, _Op) \
|
||||
GEN_METHOD_PARAMS(LM_VECTOR_ARITHMETIC_OP_SELF_VECTOR, _Op)
|
||||
|
||||
|
||||
#define MATH_VECTOR_FUNC(_Name, _TemplateParams, _TemplateParamsNames, _ExecParams, _Params) \
|
||||
namespace impl { \
|
||||
template<typename T UNPACK _TemplateParams> \
|
||||
struct _Name { \
|
||||
template<typename = void> \
|
||||
static auto exec(const T& v UNPACK _ExecParams) RESTRICT(cpu) { return std:: _Name (v UNPACK _Params); } \
|
||||
ENABLE_IF_AMP(template<typename = void> static auto exec(const T& v UNPACK _ExecParams) RESTRICT(amp) { return concurrency::precise_math:: _Name (v UNPACK _Params); }) \
|
||||
}; \
|
||||
template<typename T, LmSize N UNPACK _TemplateParams> \
|
||||
struct _Name <Vector<T, N> UNPACK _TemplateParamsNames> { \
|
||||
template<typename = void> \
|
||||
static auto exec(const Vector<T, N>& v UNPACK _ExecParams) RESTRICT(cpu, amp) { \
|
||||
Vector<decltype( _Name <T UNPACK _TemplateParamsNames>::exec(*static_cast<T*>(nullptr) UNPACK _Params)), N> result; \
|
||||
for (LmSize i = 0; i < N; ++i) { result[i] = impl:: _Name <T UNPACK _TemplateParamsNames>::exec(v[i] UNPACK _Params); } \
|
||||
return result; \
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
template<typename T UNPACK _TemplateParams> \
|
||||
auto _Name(const T& v UNPACK _ExecParams) RESTRICT(cpu, amp) { \
|
||||
return impl:: _Name <T UNPACK _TemplateParamsNames>::exec(v UNPACK _Params); \
|
||||
}
|
||||
|
||||
#define MATH_VECTOR_FUNC_ONE_PARAM(_Name) MATH_VECTOR_FUNC(_Name, (, typename TParam), (, TParam), (, TParam x), (, x))
|
||||
#define MATH_VECTOR_FUNC_NO_PARAM(_Name) MATH_VECTOR_FUNC(_Name, (), (), (), ())
|
||||
|
||||
|
||||
enum class InstructionSet {
|
||||
Generic,
|
||||
SSE,
|
||||
AVX
|
||||
};
|
||||
|
||||
template<typename T, LmSize N, InstructionSet Instructions = InstructionSet::Generic>
|
||||
struct VectorData {
|
||||
T data[N];
|
||||
|
||||
#define VECTOR_DATA_GET(_Suffix) \
|
||||
template<typename = void> \
|
||||
T& get(LmSize id) _Suffix{ \
|
||||
return data[id]; \
|
||||
} \
|
||||
template<typename = void> \
|
||||
const T& get(LmSize id) const _Suffix{ \
|
||||
return data[id]; \
|
||||
}
|
||||
GEN_METHOD(VECTOR_DATA_GET)
|
||||
|
||||
#define VECTOR_DATA_SET(_Suffix) \
|
||||
template<typename = void> \
|
||||
void set(LmSize id, T value) _Suffix { \
|
||||
data[id] = value; \
|
||||
}
|
||||
GEN_METHOD(VECTOR_DATA_SET)
|
||||
|
||||
constexpr VectorData() {}
|
||||
|
||||
#ifdef LM_AMP_SUPPORTED
|
||||
template<typename = void>
|
||||
constexpr VectorData() restrict(amp) {}
|
||||
#endif
|
||||
|
||||
#define CTOR_VA(_Suffix) \
|
||||
template<typename ... Args, LmSize M = N, typename = std::enable_if_t<(sizeof...(Args) == M) && (M > 4)>> \
|
||||
constexpr VectorData(const Args& ... rest) _Suffix : data{ rest... } {}
|
||||
GEN_METHOD(CTOR_VA)
|
||||
|
||||
//Vector2 constructors
|
||||
#define CTOR_V2(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 2>> \
|
||||
constexpr VectorData(const TA& a, const TA& b) _Suffix : data{ a, b } {}
|
||||
GEN_METHOD(CTOR_V2)
|
||||
|
||||
//Vector3 constructors
|
||||
#define CTOR_V3_0(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = typename std::enable_if<M == 3, T>::type>\
|
||||
constexpr VectorData(const TA& a, const TA& b, const TA& c) _Suffix : data{ static_cast<T>(a), static_cast<T>(b), static_cast<T>(c) } {}
|
||||
GEN_METHOD(CTOR_V3_0)
|
||||
|
||||
#define CTOR_V3_1_BASE(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 3>> \
|
||||
constexpr VectorData(const VectorData<TA, 2>& a, const TA& b) _Suffix : data{ a.data[0], a.data[1], b } {}
|
||||
GEN_METHOD(CTOR_V3_1_BASE)
|
||||
|
||||
#define CTOR_V3_2_BASE(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 3>> \
|
||||
constexpr VectorData(const TA& a, const VectorData<TA, 2>& b) _Suffix : data{ a, b.data[0], b.data[1] } {}
|
||||
GEN_METHOD(CTOR_V3_2_BASE)
|
||||
|
||||
//Vector4 constructors
|
||||
#define CTOR_V4_0_BASE(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr VectorData(const TA& a, const TA& b, const TA& c, const TA& d) _Suffix : data{ static_cast<T>(a), static_cast<T>(b), static_cast<T>(c), static_cast<T>(d) } {}
|
||||
GEN_METHOD(CTOR_V4_0_BASE)
|
||||
|
||||
#define CTOR_V4_1_BASE(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr VectorData(const TA& a, const TA& b, const VectorData<T, 2>& c) _Suffix : data{ a, b, c.data[0], c.data[1] } {}
|
||||
GEN_METHOD(CTOR_V4_1_BASE)
|
||||
|
||||
#define CTOR_V4_2_BASE(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr VectorData(const VectorData<TA, 2>& a, const TA& b, const TA& c) _Suffix : data{ a.data[0], a.data[1], b, c } {}
|
||||
GEN_METHOD(CTOR_V4_2_BASE)
|
||||
|
||||
#define CTOR_V4_3_BASE(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr VectorData(const VectorData<TA, 2>& a, const VectorData<TA, 2>& b) _Suffix : data{ a.data[0], a.data[1], b.data[0], b.data[1] } {}
|
||||
GEN_METHOD(CTOR_V4_3_BASE)
|
||||
|
||||
#define CTOR_V4_4_BASE(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr VectorData(const TA& a, const VectorData<TA, 3>& b) _Suffix : data{ a, b.data[0], b.data[1], b.data[2] } {}
|
||||
GEN_METHOD(CTOR_V4_4_BASE)
|
||||
|
||||
#define CTOR_V4_5_BASE(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr VectorData(const VectorData<TA, 3>& a, const TA& b) _Suffix : data{ a.data[0], a.data[1], a.data[2], b } {}
|
||||
GEN_METHOD(CTOR_V4_5_BASE)
|
||||
|
||||
#define CTOR_S(_Suffix) \
|
||||
template<typename Arg> \
|
||||
VectorData(Arg arg) _Suffix { \
|
||||
for (LmSize i = 0; i < N; ++i) { \
|
||||
data[i] = arg; \
|
||||
} \
|
||||
}
|
||||
GEN_METHOD(CTOR_S)
|
||||
};
|
||||
|
||||
template<typename T, LmSize N, InstructionSet Instructions = InstructionSet::Generic>
|
||||
struct Vector : public VectorData<T, N, Instructions> {
|
||||
public:
|
||||
static constexpr LmSize Size = N;
|
||||
typedef T ElementType;
|
||||
|
||||
constexpr Vector() {}
|
||||
|
||||
#ifdef LM_AMP_SUPPORTED
|
||||
template<typename = void>
|
||||
constexpr Vector() restrict(amp) {}
|
||||
#endif
|
||||
|
||||
typedef VectorData<T, N, Instructions> Base;
|
||||
|
||||
using Base::Base;
|
||||
|
||||
#define CTOR_V3_1(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 3>> \
|
||||
constexpr Vector(const Vector<TA, 2>& a, const TA& b) _Suffix : Base{ (const VectorData<TA, 2>&)a, b } {}
|
||||
GEN_METHOD(CTOR_V3_1)
|
||||
|
||||
#define CTOR_V3_2(_Suffix) \
|
||||
template<typename TA, LmSize M = N, typename = std::enable_if_t<M == 3>> \
|
||||
constexpr Vector(const TA& a, const Vector<TA, 2>& b) _Suffix : Base{ a, (const VectorData<TA, 2>&)b} {}
|
||||
GEN_METHOD(CTOR_V3_2)
|
||||
|
||||
//Vector4 constructors
|
||||
#define CTOR_V4_1(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr Vector(const TA& a, const TA& b, const Vector<T, 2>& c) _Suffix : Base {a, b, (const VectorData<T, 2>&)c} {}
|
||||
GEN_METHOD(CTOR_V4_1)
|
||||
|
||||
#define CTOR_V4_2(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr Vector(const Vector<TA, 2>& a, const TA& b, const TA& c) _Suffix : Base{(const VectorData<TA, 2>&)a, b, c}{}
|
||||
GEN_METHOD(CTOR_V4_2)
|
||||
|
||||
#define CTOR_V4_3(_Suffix) \
|
||||
template<typename TA, LmSize M = N, typename = std::enable_if_t<M == 4>> \
|
||||
constexpr Vector(const Vector<TA, 2>& a, const Vector<TA, 2>& b) _Suffix : Base { (const VectorData<TA, 2>&)a, (const VectorData<TA, 2>&)b} {}
|
||||
GEN_METHOD(CTOR_V4_3)
|
||||
|
||||
#define CTOR_V4_4(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr Vector(const TA& a, const Vector<TA, 3>& b) _Suffix : Base {a, (const VectorData<TA, 3>&)b} {}
|
||||
GEN_METHOD(CTOR_V4_4)
|
||||
|
||||
#define CTOR_V4_5(_Suffix) \
|
||||
template<typename TA, LmSize M = N,typename = std::enable_if_t<M == 4>> \
|
||||
constexpr Vector(const Vector<TA, 3>& a, const TA& b) _Suffix : Base{ (const VectorData<TA, 3>&)a, b} {}
|
||||
GEN_METHOD(CTOR_V4_5)
|
||||
|
||||
|
||||
//UnitX
|
||||
#define UNIT_X0(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 1, Vector>::type unitX() _Suffix { \
|
||||
return Vector(static_cast<T>(1)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_X0)
|
||||
|
||||
#define UNIT_X1(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 2, Vector>::type unitX() _Suffix { \
|
||||
return Vector(static_cast<T>(1), static_cast<T>(0)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_X1)
|
||||
|
||||
#define UNIT_X2(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 3, Vector>::type unitX() _Suffix { \
|
||||
return Vector(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_X2)
|
||||
|
||||
#define UNIT_X3(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 4, Vector>::type unitX() _Suffix { \
|
||||
return Vector(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_X3)
|
||||
|
||||
|
||||
//UnitY
|
||||
#define UNIT_Y0(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 2, Vector>::type unitY() _Suffix { \
|
||||
return Vector(static_cast<T>(0), static_cast<T>(1)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_Y0)
|
||||
|
||||
#define UNIT_Y1(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 3, Vector>::type unitY() _Suffix { \
|
||||
return Vector(static_cast<T>(0), static_cast<T>(1), static_cast<T>(0)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_Y1)
|
||||
|
||||
#define UNIT_Y2(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 4, Vector>::type unitY() _Suffix { \
|
||||
return Vector(static_cast<T>(0), static_cast<T>(1), static_cast<T>(0), static_cast<T>(0)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_Y2)
|
||||
|
||||
//UnitZ
|
||||
#define UNIT_Z0(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 3, Vector>::type unitZ() _Suffix { \
|
||||
return Vector(static_cast<T>(0), static_cast<T>(0), static_cast<T>(1)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_Z0)
|
||||
|
||||
#define UNIT_Z1(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 4, Vector>::type unitZ() _Suffix { \
|
||||
return Vector(static_cast<T>(0), static_cast<T>(0), static_cast<T>(1), static_cast<T>(0)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_Z1)
|
||||
|
||||
//UnitW
|
||||
#define UNIT_W0(_Suffix) \
|
||||
template<LmSize M = N> \
|
||||
static typename std::enable_if<M == 4, Vector>::type unitW() _Suffix { \
|
||||
return Vector(static_cast<T>(0), static_cast<T>(0), static_cast<T>(0), static_cast<T>(1)); \
|
||||
}
|
||||
GEN_METHOD(UNIT_W0)
|
||||
|
||||
//EMPTY_SUFFIX
|
||||
|
||||
#define VECTOR_ITEM_ACCESSOR_BASE(_Name, _Index, _Modifier, _Restrict) \
|
||||
template<LmSize S = Size, typename = std::enable_if_t<(S == Size) && (S > _Index)>> \
|
||||
_Modifier auto& _Name () _Modifier _Restrict { return this->get(_Index); }
|
||||
|
||||
#define VECTOR_ITEM_ACCESSOR(_Name, _Index) \
|
||||
VECTOR_ITEM_ACCESSOR_BASE(_Name, _Index, EMPTY_SUFFIX, EMPTY_SUFFIX) \
|
||||
VECTOR_ITEM_ACCESSOR_BASE(_Name, _Index, const, EMPTY_SUFFIX) \
|
||||
ENABLE_IF_AMP(VECTOR_ITEM_ACCESSOR_BASE(_Name, _Index, EMPTY_SUFFIX, restrict(amp)) ) \
|
||||
ENABLE_IF_AMP(VECTOR_ITEM_ACCESSOR_BASE(_Name, _Index, const, restrict(amp)) )
|
||||
|
||||
//accessors
|
||||
VECTOR_ITEM_ACCESSOR(x, 0);
|
||||
VECTOR_ITEM_ACCESSOR(y, 1);
|
||||
VECTOR_ITEM_ACCESSOR(z, 2);
|
||||
VECTOR_ITEM_ACCESSOR(w, 3);
|
||||
|
||||
|
||||
#define SLICE(_Prefix, _Suffix) \
|
||||
template<LmSize Offset, LmSize Length, typename = std::enable_if_t<Offset + Length <= N>> \
|
||||
_Prefix Vector<T, Length>& slice() _Suffix { \
|
||||
return *((Vector<T, Length>*)&this->data[Offset]); \
|
||||
}
|
||||
GEN_METHOD2(SLICE)
|
||||
|
||||
#define LINEAR_SLICE_ACCESSOR_BASE(_Name, _Offset, _Length, _Prefix, _Suffix) \
|
||||
template<LmSize SliceOffset = _Offset, LmSize SliceLength = _Length, typename = std::enable_if_t<(SliceOffset == _Offset) && (SliceLength == _Length) && ((SliceOffset + SliceLength) <= N)>> \
|
||||
_Prefix auto& _Name () _Suffix { return slice<SliceOffset, SliceLength>(); }
|
||||
|
||||
|
||||
#define LM_VECTOR_LINEAR_SLICE_ACCESSOR_XY(_Prefix, _Suffix) LINEAR_SLICE_ACCESSOR_BASE(xy, 0, 2, _Prefix, _Suffix)
|
||||
#define LM_VECTOR_LINEAR_SLICE_ACCESSOR_XYZ(_Prefix, _Suffix) LINEAR_SLICE_ACCESSOR_BASE(xyz, 0, 3, _Prefix, _Suffix)
|
||||
#define LM_VECTOR_LINEAR_SLICE_ACCESSOR_XYZW(_Prefix, _Suffix) LINEAR_SLICE_ACCESSOR_BASE(xyzw, 0, 4, _Prefix, _Suffix)
|
||||
#define LM_VECTOR_LINEAR_SLICE_ACCESSOR_YZ(_Prefix, _Suffix) LINEAR_SLICE_ACCESSOR_BASE(yz, 1, 2, _Prefix, _Suffix)
|
||||
#define LM_VECTOR_LINEAR_SLICE_ACCESSOR_YZW(_Prefix, _Suffix) LINEAR_SLICE_ACCESSOR_BASE(yzw, 1, 3, _Prefix, _Suffix)
|
||||
#define LM_VECTOR_LINEAR_SLICE_ACCESSOR_ZW(_Prefix, _Suffix) LINEAR_SLICE_ACCESSOR_BASE(zw, 2, 2, _Prefix, _Suffix)
|
||||
|
||||
GEN_METHOD2(LM_VECTOR_LINEAR_SLICE_ACCESSOR_XY)
|
||||
GEN_METHOD2(LM_VECTOR_LINEAR_SLICE_ACCESSOR_XYZ)
|
||||
GEN_METHOD2(LM_VECTOR_LINEAR_SLICE_ACCESSOR_XYZW)
|
||||
GEN_METHOD2(LM_VECTOR_LINEAR_SLICE_ACCESSOR_YZ)
|
||||
GEN_METHOD2(LM_VECTOR_LINEAR_SLICE_ACCESSOR_YZW)
|
||||
GEN_METHOD2(LM_VECTOR_LINEAR_SLICE_ACCESSOR_ZW)
|
||||
|
||||
|
||||
#define LEN_SQ(_Prefix, _Suffix) \
|
||||
template<typename TR = MultiplyType<T>> \
|
||||
_Prefix auto lengthSquared() _Suffix { \
|
||||
TR result = DefaultValues<TR>::zero(); \
|
||||
for (LmSize i = 0; i < N; ++i) { \
|
||||
result += this->get(i) * this->get(i); \
|
||||
} \
|
||||
return result;\
|
||||
}
|
||||
|
||||
GEN_METHOD2(LEN_SQ)
|
||||
|
||||
auto length() const RESTRICT(cpu);
|
||||
#if defined(LM_AMP_SUPPORTED)
|
||||
auto length() const RESTRICT(amp);
|
||||
#endif
|
||||
|
||||
#define OP_INDEX(_Prefix, _Suffix) \
|
||||
template<typename = void> \
|
||||
_Prefix T& operator [] (LmSize id) _Suffix { \
|
||||
return this->get(id); \
|
||||
}
|
||||
GEN_METHOD2(OP_INDEX)
|
||||
|
||||
#define NORMALIZED(_Suffix) \
|
||||
auto normalized() _Suffix { \
|
||||
return (*this) / length(); \
|
||||
}
|
||||
GEN_METHOD_CONST(NORMALIZED)
|
||||
|
||||
|
||||
/*LM_VECTOR_ARITHMETIC_OP(+);
|
||||
LM_VECTOR_ARITHMETIC_OP(-);
|
||||
LM_VECTOR_ARITHMETIC_OP(*);
|
||||
LM_VECTOR_ARITHMETIC_OP(/ );*/
|
||||
|
||||
template<typename = void>
|
||||
bool equals(const Vector& other, T tolerance) const;
|
||||
ENABLE_IF_AMP(template<typename = void> bool equals(const Vector& other, T tolerance) const restrict(amp); )
|
||||
|
||||
#define OP_NEG(_Suffix) \
|
||||
template<typename = void> \
|
||||
auto operator-() const _Suffix { \
|
||||
Vector<typename std::decay<decltype(-this->x())>::type, Size> result; \
|
||||
for (LmSize i = 0; i < Size; ++i) { \
|
||||
result[i] = -this->get(i); \
|
||||
} \
|
||||
return result; \
|
||||
}
|
||||
|
||||
GEN_METHOD(OP_NEG)
|
||||
|
||||
#define OP_EQ(_Suffix) \
|
||||
template<typename T2> \
|
||||
bool operator==(const Vector<T2, Size>& right) const _Suffix { \
|
||||
for (LmSize i = 0; i < Size; ++i) { \
|
||||
if (this->get(i) != right[i]) { \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
GEN_METHOD(OP_EQ)
|
||||
|
||||
#define OP_NEQ(_Suffix) \
|
||||
template<typename T2> \
|
||||
bool operator!=(const Vector<T2, Size>& right) const _Suffix { \
|
||||
for (LmSize i = 0; i < Size; ++i) { \
|
||||
if (this->get(i) != right[i]) { \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
GEN_METHOD(OP_NEQ)
|
||||
|
||||
#define OP_CAST_RAW(_Prefix, _Suffix) \
|
||||
template<typename = void> \
|
||||
explicit operator _Prefix T*() _Suffix { \
|
||||
return Size == 0 ? nullptr : &this->get(0); \
|
||||
}
|
||||
GEN_METHOD2(OP_CAST_RAW)
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename T, typename U>
|
||||
auto cross(const Vector<T, 3>& a, const Vector<U, 3>& b) RESTRICT(cpu, amp) {
|
||||
return Vector<MultiplyType<T, U>, 3>(
|
||||
(a[1] * b[2]) - (a[2] * b[1]),
|
||||
(a[2] * b[0]) - (a[0] * b[2]),
|
||||
(a[0] * b[1]) - (a[1] * b[0]));
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, LmSize N>
|
||||
auto dot(const Vector<T1, N>& left, const Vector<T2, N>& right)RESTRICT(cpu, amp) {
|
||||
auto result = DefaultValues<MultiplyType<T1, T2>>::zero();
|
||||
for (LmSize i = 0; i < N; ++i) {
|
||||
result += left[i] * right[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template<typename T, LmSize N>
|
||||
auto normalize(const Vector<T, N>& v) RESTRICT(cpu, amp) {
|
||||
return v.normalized();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename TA, typename TB, LmSize N, typename TC>
|
||||
auto lerp(const Vector<TA, N>& a, const Vector<TB, N>& b, TC c)RESTRICT(cpu, amp) {
|
||||
return a * (DefaultValues<TC>::one() - c) + b * c;
|
||||
}
|
||||
|
||||
template<typename T, LmSize N>
|
||||
auto all(const Vector<T, N>& v) RESTRICT(cpu, amp) {
|
||||
for (LmSize i = 0; i < N; ++i) {
|
||||
if (v[i] == DefaultValues<T>::zero()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, LmSize N>
|
||||
auto any(const Vector<T, N>& v) RESTRICT(cpu, amp) {
|
||||
for (LmSize i = 0; i < N; ++i) {
|
||||
if (v[i] != static_cast<T>(0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
namespace impl {
|
||||
template<typename T>
|
||||
struct abs {};
|
||||
template<>
|
||||
struct abs<float> {
|
||||
static auto exec(const float& v) RESTRICT(cpu) { return std::fabs(v); }
|
||||
ENABLE_IF_AMP(static auto exec(const float& v) RESTRICT(amp) { return concurrency::precise_math::fabs(v); })
|
||||
};
|
||||
template<>
|
||||
struct abs<double> {
|
||||
static auto exec(const double& v) RESTRICT(cpu) { return std::fabs(v); }
|
||||
ENABLE_IF_AMP(static auto exec(const double& v) RESTRICT(amp) { return concurrency::precise_math::fabs(v); })
|
||||
};
|
||||
|
||||
template<typename T, LmSize N>
|
||||
struct abs<Vector<T, N>> {
|
||||
static auto exec(const Vector<T, N>& v) RESTRICT(cpu, amp) {
|
||||
Vector<T, N> result;
|
||||
for (LmSize i = 0; i < N; ++i) { result[i] = abs<T>::exec(v[i]); }
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
LM_VECTOR_ARITHMETIC_OP(+);
|
||||
LM_VECTOR_ARITHMETIC_OP(-);
|
||||
LM_VECTOR_ARITHMETIC_OP(*);
|
||||
LM_VECTOR_ARITHMETIC_OP(/ );
|
||||
|
||||
|
||||
template<typename T>
|
||||
auto abs(const T& v) RESTRICT(cpu, amp) {
|
||||
return impl::abs<T>::exec(v);
|
||||
}
|
||||
|
||||
|
||||
MATH_VECTOR_FUNC_ONE_PARAM(pow);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(sin);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(cos);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(acos);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(asin);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(cosh);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(sinh);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(tan);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(atan);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(floor);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(ceil);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(exp);
|
||||
MATH_VECTOR_FUNC_NO_PARAM(log);
|
||||
|
||||
MATH_VECTOR_FUNC_NO_PARAM(sqrt);
|
||||
|
||||
#define LM_VEC_METHOD_LENGTH(_Suffix) \
|
||||
template<typename T, LmSize N, InstructionSet Instructions> \
|
||||
auto Vector<T, N, Instructions>::length() const _Suffix { \
|
||||
return lm::sqrt(lengthSquared()); \
|
||||
}
|
||||
|
||||
GEN_METHOD(LM_VEC_METHOD_LENGTH)
|
||||
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
namespace impl {
|
||||
template<typename T>
|
||||
struct min {
|
||||
static auto exec(const T& a, const T& b) RESTRICT(cpu, amp) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, LmSize N>
|
||||
struct min<Vector<T, N>> {
|
||||
static auto exec(const Vector<T, N>& a, const Vector<T, N>& b) RESTRICT(cpu, amp) {
|
||||
Vector<T, N> result;
|
||||
for (LmSize i = 0; i < N; ++i) { result[i] = impl::min<T>::exec(a[i], b[i]); }
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto min(const T& a, const T& b) RESTRICT(cpu, amp) {
|
||||
return impl::min<T>::exec(a, b);
|
||||
}
|
||||
|
||||
template<typename T, LmSize N, typename = std::enable_if_t<(N > 0)>>
|
||||
auto min(const Vector<T, N>& v) RESTRICT(cpu, amp) {
|
||||
LmSize id = 0;
|
||||
for (LmSize i = 1; i < N; ++i) {
|
||||
if (v[i] < v[id]) {
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
return v[id];
|
||||
}
|
||||
|
||||
template<typename T, LmSize N, typename = std::enable_if_t <(N > 0)>>
|
||||
auto max(const Vector<T, N>& v) RESTRICT(cpu, amp) {
|
||||
LmSize id = 0;
|
||||
for (LmSize i = 1; i < N; ++i) {
|
||||
if (v[i] > v[id]) {
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
return v[id];
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
template<typename T>
|
||||
struct max {
|
||||
static auto exec(const T& a, const T& b) RESTRICT(cpu, amp) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, LmSize N>
|
||||
struct max<Vector<T, N>> {
|
||||
static auto exec(const Vector<T, N>& a, const Vector<T, N>& b) RESTRICT(cpu, amp) {
|
||||
Vector<T, N> result;
|
||||
for (LmSize i = 0; i < N; ++i) { result[i] = impl::max<T>::exec(a[i], b[i]); }
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto max(const T& a, const T& b) RESTRICT(cpu, amp) {
|
||||
return impl::max<T>::exec(a, b);
|
||||
}
|
||||
|
||||
template<typename T, typename TRange>
|
||||
auto clamp(const T& a, const TRange& minValue, const TRange& maxValue) RESTRICT(cpu, amp) {
|
||||
return lm::min(lm::max(a, minValue), maxValue);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto saturate(const T& a) RESTRICT(cpu, amp) {
|
||||
T result;
|
||||
for (LmSize i = 0; i < T::Size; ++i) {
|
||||
result[i] = lm::min(lm::max(a[i], static_cast<typename T::ElementType>(0)), static_cast<typename T::ElementType>(1));
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace impl {
|
||||
template<typename T>
|
||||
struct degrees {
|
||||
static auto exec(const T& a) RESTRICT(cpu, amp) {
|
||||
return (static_cast<T>(180) / static_cast<T>(pi_d)) * a;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, LmSize N>
|
||||
struct degrees<Vector<T, N>> {
|
||||
static auto exec(const Vector<T, N>& a) RESTRICT(cpu, amp) {
|
||||
Vector<T, N> result;
|
||||
for (LmSize i = 0; i < N; ++i) { result[i] = impl::degrees<T>::exec(a[i]); }
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto degrees(const T& a) RESTRICT(cpu, amp) {
|
||||
return impl::degrees<T>::exec(a);
|
||||
}
|
||||
|
||||
#define LM_VECTOR_EQUALS(_Suffix) \
|
||||
template<typename T, LmSize N, InstructionSet Instructions> \
|
||||
template<typename> \
|
||||
bool Vector<T, N, Instructions>::equals(const Vector<T, N, Instructions>& other, T tolerance) const _Suffix { \
|
||||
for (LmSize i = 0; i < N; ++i) { \
|
||||
if (lm::abs(this->get(i) - other.get(i)) >= tolerance) { \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
||||
GEN_METHOD(LM_VECTOR_EQUALS)
|
||||
|
||||
template<typename T, LmSize N, InstructionSet Instructions>
|
||||
bool equals(const Vector<T, N, Instructions>& a, const Vector<T, N, Instructions>& b, T tolerance) RESTRICT(cpu, amp) {
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2, LmSize N>
|
||||
auto distance(const Vector<T1, N>& v1, const Vector<T2, N>& v2) RESTRICT(cpu, amp) {
|
||||
return (v2 - v1).length();
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef Vector<float, 2> float2;
|
||||
typedef Vector<float, 3> float3;
|
||||
typedef Vector<float, 4> float4;
|
||||
typedef Vector<double, 2> double2;
|
||||
typedef Vector<double, 3> double3;
|
||||
typedef Vector<double, 4> double4;
|
||||
}
|
||||
#endif // lm_vector_h__
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
#ifndef lm_vector_avx_h__
|
||||
#define lm_vector_avx_h__
|
||||
|
||||
#include "lm_vector.h"
|
||||
#include <intrin.h>
|
||||
|
||||
|
||||
namespace lm {
|
||||
|
||||
template<>
|
||||
struct VectorData<double, 4, InstructionSet::AVX> {
|
||||
VectorData() {
|
||||
avxValue = _mm256_setzero_pd();
|
||||
}
|
||||
|
||||
VectorData(__m256d value) : avxValue(value) {
|
||||
|
||||
}
|
||||
VectorData(double value) {
|
||||
avxValue = _mm256_set_pd(value, value, value, value);
|
||||
}
|
||||
|
||||
VectorData(double x, double y, double z, double w) {
|
||||
avxValue = _mm256_set_pd(w, z, y, x);
|
||||
}
|
||||
|
||||
|
||||
template<LmSize Index>
|
||||
double get() const {
|
||||
static_assert(Index < 4);
|
||||
alignas(256) double buffer[4];
|
||||
_mm256_store_pd(&buffer[0], avxValue);
|
||||
return buffer[Index];
|
||||
}
|
||||
double get(LmSize id) const {
|
||||
if (id == 0) {
|
||||
return get<0>();
|
||||
}
|
||||
else if (id == 1) {
|
||||
return get<1>();
|
||||
}
|
||||
else if (id == 2) {
|
||||
return get<2>();
|
||||
}
|
||||
else {
|
||||
return get<3>();
|
||||
}
|
||||
}
|
||||
|
||||
__m256d avxValue;
|
||||
};
|
||||
|
||||
using double4_avx = Vector<double, 4, InstructionSet::AVX>;
|
||||
|
||||
double dot(double4_avx l, double4_avx r) {
|
||||
//AVX code
|
||||
|
||||
auto m = _mm256_mul_pd(l.avxValue, r.avxValue);
|
||||
auto a0 = _mm256_hadd_pd(m, m);
|
||||
auto a1 = _mm256_permute4x64_pd(a0, _MM_SHUFFLE(1, 3, 1, 3));
|
||||
return _mm_cvtsd_f64(_mm256_castpd256_pd128(_mm256_hadd_pd(a1,a1)));
|
||||
}
|
||||
|
||||
|
||||
double4_avx operator * (double4_avx l, double4_avx r) { return { _mm256_mul_pd(l.avxValue, r.avxValue) }; }
|
||||
double4_avx operator / (double4_avx l, double4_avx r) { return { _mm256_div_pd(l.avxValue, r.avxValue) }; }
|
||||
double4_avx operator + (double4_avx l, double4_avx r) { return { _mm256_add_pd(l.avxValue, r.avxValue) }; }
|
||||
double4_avx operator - (double4_avx l, double4_avx r) { return { _mm256_sub_pd(l.avxValue, r.avxValue) }; }
|
||||
|
||||
double4_avx& operator *= (double4_avx& l, double4_avx r) { l = l * r; return l; }
|
||||
double4_avx& operator /= (double4_avx& l, double4_avx r) { l = l / r; return l; }
|
||||
double4_avx& operator += (double4_avx& l, double4_avx r) { l = l + r; return l; }
|
||||
double4_avx& operator -= (double4_avx& l, double4_avx r) { l = l - r; return l; }
|
||||
|
||||
double4_avx operator == (double4_avx l, double4_avx r) { return { _mm256_cmp_pd(l.avxValue, r.avxValue, _CMP_EQ_OQ) }; }
|
||||
double4_avx operator != (double4_avx l, double4_avx r) { return { _mm256_cmp_pd(l.avxValue, r.avxValue, _CMP_NEQ_OQ) }; }
|
||||
double4_avx operator < (double4_avx l, double4_avx r) { return { _mm256_cmp_pd(l.avxValue, r.avxValue, _CMP_LT_OQ) }; }
|
||||
double4_avx operator <= (double4_avx l, double4_avx r) { return { _mm256_cmp_pd(l.avxValue, r.avxValue, _CMP_LE_OQ) }; }
|
||||
double4_avx operator > (double4_avx l, double4_avx r) { return { _mm256_cmp_pd(l.avxValue, r.avxValue, _CMP_GT_OQ) }; }
|
||||
double4_avx operator >= (double4_avx l, double4_avx r) { return { _mm256_cmp_pd(l.avxValue, r.avxValue, _CMP_GE_OQ) }; }
|
||||
|
||||
double4_avx min(double4_avx l, double4_avx r) { return { _mm256_min_pd(l.avxValue, r.avxValue) }; }
|
||||
double4_avx max(double4_avx l, double4_avx r) { return { _mm256_max_pd(l.avxValue, r.avxValue) }; }
|
||||
|
||||
}
|
||||
#endif // lm_vector_avx_h__
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
#ifndef lm_vector_sse_h__
|
||||
#define lm_vector_sse_h__
|
||||
|
||||
#include "lm_vector.h"
|
||||
#include <intrin.h>
|
||||
|
||||
|
||||
namespace lm {
|
||||
|
||||
template<>
|
||||
struct VectorData<float, 4, InstructionSet::SSE> {
|
||||
|
||||
VectorData() {
|
||||
sseValue = _mm_setzero_ps();
|
||||
}
|
||||
|
||||
VectorData(float value) {
|
||||
sseValue = _mm_set_ps1(value);
|
||||
}
|
||||
|
||||
VectorData(float x, float y, float z, float w) {
|
||||
sseValue = _mm_set_ps(w, z, y, x);
|
||||
}
|
||||
|
||||
VectorData(__m128 value) : sseValue(value){
|
||||
}
|
||||
|
||||
|
||||
template<LmSize Index>
|
||||
float get() const {
|
||||
static_assert(Index < 4);
|
||||
if constexpr(Index == 0) {
|
||||
return _mm_cvtss_f32(sseValue);
|
||||
}
|
||||
else if constexpr(Index == 1) {
|
||||
return _mm_cvtss_f32(_mm_shuffle_ps(sseValue, sseValue, _MM_SHUFFLE(1, 1, 1, 1)));
|
||||
}
|
||||
else if constexpr(Index == 2) {
|
||||
return _mm_cvtss_f32(_mm_shuffle_ps(sseValue, sseValue, _MM_SHUFFLE(2, 2, 2, 2)));
|
||||
}
|
||||
else {
|
||||
return _mm_cvtss_f32(_mm_shuffle_ps(sseValue, sseValue, _MM_SHUFFLE(3, 3, 3, 3)));
|
||||
}
|
||||
}
|
||||
|
||||
float get(LmSize id) const {
|
||||
if (id == 0) {
|
||||
return get<0>();
|
||||
}
|
||||
else if (id == 1) {
|
||||
return get<1>();
|
||||
}
|
||||
else if (id == 2) {
|
||||
return get<2>();
|
||||
}
|
||||
else {
|
||||
return get<3>();
|
||||
}
|
||||
}
|
||||
|
||||
template<LmSize Index>
|
||||
void set(float value) {
|
||||
static_assert(Index < 4);
|
||||
if constexpr(Index == 0) {
|
||||
sseValue = _mm_move_ss(sseValue, _mm_set_ss(value));
|
||||
}
|
||||
if constexpr(Index == 1) {
|
||||
auto temp = _mm_move_ss(sseValue, _mm_set_ss(value));
|
||||
temp = _mm_shuffle_ps(temp, temp, _MM_SHUFFLE(3, 2, 0, 0));
|
||||
sseValue = _mm_move_ss(temp, sseValue);
|
||||
}
|
||||
if constexpr(Index == 2) {
|
||||
auto temp = _mm_move_ss(sseValue, _mm_set_ss(value));
|
||||
temp = _mm_shuffle_ps(temp, temp, _MM_SHUFFLE(3, 0, 1, 0));
|
||||
sseValue = _mm_move_ss(temp, sseValue);
|
||||
}
|
||||
if constexpr(Index == 3) {
|
||||
auto temp = _mm_move_ss(sseValue, _mm_set_ss(value));
|
||||
temp = _mm_shuffle_ps(temp, temp, _MM_SHUFFLE(0, 2, 1, 0));
|
||||
sseValue = _mm_move_ss(temp, sseValue);
|
||||
}
|
||||
}
|
||||
|
||||
void set(LmSize id, float value) {
|
||||
if (id == 0) {
|
||||
set<0>(value);
|
||||
}
|
||||
else if (id == 1) {
|
||||
set<1>(value);
|
||||
}
|
||||
else if (id == 2) {
|
||||
set<2>(value);
|
||||
}
|
||||
else {
|
||||
set<3>(value);
|
||||
}
|
||||
}
|
||||
|
||||
auto mask() const {
|
||||
return _mm_movemask_ps(sseValue) & 0x7;
|
||||
}
|
||||
|
||||
__m128 sseValue;
|
||||
};
|
||||
|
||||
using float4_sse = Vector<float, 4, InstructionSet::SSE>;
|
||||
|
||||
float4_sse operator * (float4_sse l, float4_sse r) { return { _mm_mul_ps(l.sseValue, r.sseValue) }; }
|
||||
float4_sse operator / (float4_sse l, float4_sse r) { return { _mm_div_ps(l.sseValue, r.sseValue) }; }
|
||||
float4_sse operator + (float4_sse l, float4_sse r) { return { _mm_add_ps(l.sseValue, r.sseValue) }; }
|
||||
float4_sse operator - (float4_sse l, float4_sse r) { return { _mm_sub_ps(l.sseValue, r.sseValue) }; }
|
||||
|
||||
float4_sse& operator *= (float4_sse& l, float4_sse r) { l = l * r; return l; }
|
||||
float4_sse& operator /= (float4_sse& l, float4_sse r) { l = l / r; return l; }
|
||||
float4_sse& operator += (float4_sse& l, float4_sse r) { l = l + r; return l; }
|
||||
float4_sse& operator -= (float4_sse& l, float4_sse r) { l = l - r; return l; }
|
||||
|
||||
float4_sse operator == (float4_sse l, float4_sse r) { return { _mm_cmpeq_ps(l.sseValue, r.sseValue) }; }
|
||||
float4_sse operator != (float4_sse l, float4_sse r) { return { _mm_cmpneq_ps(l.sseValue, r.sseValue) }; }
|
||||
float4_sse operator < (float4_sse l, float4_sse r) { return { _mm_cmplt_ps(l.sseValue, r.sseValue) }; }
|
||||
float4_sse operator <= (float4_sse l, float4_sse r) { return { _mm_cmple_ps(l.sseValue, r.sseValue) }; }
|
||||
float4_sse operator > (float4_sse l, float4_sse r) { return { _mm_cmpgt_ps(l.sseValue, r.sseValue) }; }
|
||||
float4_sse operator >= (float4_sse l, float4_sse r) { return { _mm_cmpge_ps(l.sseValue, r.sseValue) }; }
|
||||
|
||||
float4_sse min(float4_sse l, float4_sse r) { return {_mm_min_ps(l.sseValue, r.sseValue)}; }
|
||||
float4_sse max(float4_sse l, float4_sse r) { return {_mm_max_ps(l.sseValue, r.sseValue)}; }
|
||||
|
||||
float min(float4_sse l) {
|
||||
auto ml = _mm_min_ps(l.sseValue, _mm_shuffle_ps(l.sseValue, l.sseValue, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||
return _mm_cvtss_f32(_mm_min_ps(ml, _mm_shuffle_ps(ml, ml, _MM_SHUFFLE(1, 1, 1, 1))));
|
||||
}
|
||||
|
||||
float max(float4_sse l) {
|
||||
auto ml = _mm_max_ps(l.sseValue, _mm_shuffle_ps(l.sseValue, l.sseValue, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||
return _mm_cvtss_f32(_mm_max_ps(ml, _mm_shuffle_ps(ml, ml, _MM_SHUFFLE(1, 1, 1, 1))));
|
||||
}
|
||||
|
||||
float sum(float4_sse v) {
|
||||
//SSE3 code
|
||||
auto tmp = _mm_hadd_ps(v.sseValue, v.sseValue);
|
||||
return _mm_cvtss_f32(_mm_hadd_ps(tmp, tmp));
|
||||
}
|
||||
|
||||
float dot(float4_sse l, float4_sse r) {
|
||||
//SSE4 code
|
||||
return _mm_cvtss_f32(_mm_dp_ps(l.sseValue, r.sseValue, 0xff));
|
||||
}
|
||||
|
||||
//_mm_dp_ps
|
||||
}
|
||||
|
||||
#endif // lm_vector_sse_h__
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#ifndef lm_vector_traits_h__
|
||||
#define lm_vector_traits_h__
|
||||
|
||||
#include "lm_traits.h"
|
||||
#include "lm_types.h"
|
||||
|
||||
namespace lm {
|
||||
namespace Detail {
|
||||
template<typename T>
|
||||
struct IsVector : public std::false_type {};
|
||||
|
||||
template<typename T, lm::LmSize N>
|
||||
struct IsVector<lm::Vector<T, N>> : public std::true_type {};
|
||||
|
||||
template<typename T, bool IsVector>
|
||||
struct VectorSize : std::integral_constant<lm::LmSize, 1> {};
|
||||
|
||||
template<typename T>
|
||||
struct VectorSize<T, true> : std::integral_constant<lm::LmSize, T::Size> {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct IsVector : public Detail::IsVector<std::remove_cv_t<T>> {};
|
||||
|
||||
template<typename T>
|
||||
struct VectorSize : Detail::VectorSize<T, IsVector<T>::value> {};
|
||||
|
||||
}
|
||||
|
||||
#endif // lm_vector_traits_h__
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "lm_vector.h"
|
||||
#include "lm_matrix.h"
|
||||
#include "lm_plane.h"
|
||||
#include "lm_common_intrin.h"
|
||||
#include "lm_plane_intrin.h"
|
||||
#include "lm_quaternion.h"
|
||||
#include "lm_quaternion_intrin.h"
|
||||
#include "lm_stdio.h"
|
||||
#include "lm_half.h"
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<ItemsProjectGuid>{ac7a7e55-b112-4c1c-a6d0-f35ad8bf5164}</ItemsProjectGuid>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectCapability Include="SourceItemsFromImports" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)lmath\**\*.h*" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="$(MSBuildThisFileDirectory)lmath\**\*.c*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+544
@@ -0,0 +1,544 @@
|
||||
#include "../lmath/lmath.h"
|
||||
#include "../lmath/lm_vector_sse.h"
|
||||
#include "../lmath/lm_vector_avx.h"
|
||||
#include <iostream>
|
||||
#include <amp.h>
|
||||
#include <intrin.h>
|
||||
|
||||
using namespace concurrency;
|
||||
using namespace lm;
|
||||
|
||||
void TestCPU() restrict(cpu) {
|
||||
|
||||
double4_avx d0(1.0, 0, 1, 4);
|
||||
auto dm0 = d0.get<0>();
|
||||
auto dm1 = d0.get<1>();
|
||||
auto dm2 = d0.get<2>();
|
||||
auto dm3 = d0.get<3>();
|
||||
|
||||
double dt = lm::dot(d0, d0);
|
||||
|
||||
auto pp = lm::min(double4_avx(1, 2, 3, 4), double4_avx(4, 3, 2, 1));
|
||||
auto ppp0 = pp.get<0>();
|
||||
auto ppp1 = pp.get<1>();
|
||||
auto ppp2 = pp.get<2>();
|
||||
auto ppp3 = pp.get<3>();
|
||||
|
||||
auto pplen = pp.length();
|
||||
|
||||
auto f_sse3 = float4_sse(3) * float4_sse(4);
|
||||
|
||||
auto l = float4_sse(0, 1, 2, 3);
|
||||
|
||||
auto ls = lm::sum(l);
|
||||
|
||||
auto lx = l.get<0>();
|
||||
|
||||
Vector<uint16_t, 3> p00(0U);
|
||||
Vector<uint16_t, 3> p0;
|
||||
Vector<uint16_t, 5> p1((uint16_t)0U, (uint16_t)1U, (uint16_t)2U, (uint16_t)3U, (uint16_t)4U);
|
||||
|
||||
Vector<uint16_t, 2> p3((uint16_t)0U, (uint16_t)1U);
|
||||
Vector<uint16_t, 3> p4((uint16_t)0U, (uint16_t)1U, (uint16_t)2U);
|
||||
Vector<uint16_t, 4> p5((uint16_t)0U, (uint16_t)1U, (uint16_t)2U, (uint16_t)3U);
|
||||
|
||||
Vector<uint16_t, 2>::unitX();
|
||||
Vector<uint16_t, 3>::unitX();
|
||||
Vector<uint16_t, 4>::unitX();
|
||||
|
||||
auto p3x = p3.y();
|
||||
|
||||
|
||||
p0.lengthSquared();
|
||||
// p0.length();
|
||||
|
||||
auto pp0 = p0 / 2.0f;
|
||||
auto pp1 = p0 * 2.0f;
|
||||
auto pp2 = p0 + 2.0f;
|
||||
auto pp3 = p0 - 2.0f;
|
||||
|
||||
p0 /= 2;
|
||||
p0 *= 2;
|
||||
p0 += 2;
|
||||
p0 -= 2;
|
||||
//p0.normalized();
|
||||
|
||||
auto& v = p0.slice<1, 2>();
|
||||
|
||||
Vector<float, 3> v0(1.0f, 2.0f, 3.0f);
|
||||
v0 = -v0;
|
||||
|
||||
v0 == v0;
|
||||
v0 != v0;
|
||||
|
||||
auto v1 = cross(v0, v0 + 1.0f);
|
||||
auto v2 = dot(v0, v0 + 1.0f);
|
||||
auto v3 = normalize(v0);
|
||||
}
|
||||
|
||||
void TestAMP() restrict(amp) {
|
||||
Vector<uint32_t, 3> p00(0U);
|
||||
|
||||
Vector<uint32_t, 3> p0;
|
||||
Vector<uint32_t, 5> p1(0U, 1U, 2U, 3U, 4U);
|
||||
|
||||
Vector<uint32_t, 2> p3(0U, 1U);
|
||||
Vector<uint32_t, 3> p4(0U, 1U, 2U);
|
||||
Vector<uint32_t, 4> p5(0U, 1U, 2U, 3U);
|
||||
|
||||
Vector<uint32_t, 2>::unitX();
|
||||
Vector<uint32_t, 3>::unitX();
|
||||
Vector<uint32_t, 4>::unitX();
|
||||
|
||||
auto& v = p0.slice<1, 2>();
|
||||
|
||||
|
||||
|
||||
auto pp0 = p0 / 2.0f;
|
||||
auto pp1 = p0 * 2.0f;
|
||||
auto pp2 = p0 + 2.0f;
|
||||
auto pp3 = p0 - 2.0f;
|
||||
|
||||
p0 /= 2;
|
||||
p0 *= 2;
|
||||
p0 += 2;
|
||||
p0 -= 2;
|
||||
|
||||
Vector<float, 3> v0(1.0f, 2.0f, 3.0f);
|
||||
v0 = -v0;
|
||||
|
||||
v0 == v0;
|
||||
v0 != v0;
|
||||
|
||||
auto v1 = cross(v0, v0 + 1.0f);
|
||||
auto v2 = dot(v0, v0 + 1.0f);
|
||||
auto v3 = normalize(v0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
TestCPU();
|
||||
|
||||
Vector<uint16_t, 3> p0;
|
||||
|
||||
std::vector<lm::float3> amp_vector;
|
||||
std::vector<lm::float3> amp_result_vector(amp_vector.size());
|
||||
|
||||
array_view<lm::float3, 1> arr(amp_vector);
|
||||
array_view<lm::float3, 1> arr_result(amp_result_vector);
|
||||
arr_result.discard_data();
|
||||
|
||||
|
||||
parallel_for_each(arr.extent, [=](index<1> idx) restrict(amp) {
|
||||
TestAMP();
|
||||
});
|
||||
|
||||
|
||||
/*float4x4 ta;
|
||||
float4x4 tb;
|
||||
ta = tb;
|
||||
|
||||
float4 pp(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
float4 pn = -pp;
|
||||
|
||||
auto& xyzw = pp.xyzw();
|
||||
auto& xyz = pp.xyz();
|
||||
auto& xy = pp.xy();
|
||||
|
||||
auto& yzw = pp.yzw();
|
||||
auto& yz = pp.yz();
|
||||
|
||||
auto& zw = pp.zw();
|
||||
|
||||
auto& xx = pn.x();
|
||||
auto& yy = pn.y();
|
||||
auto& zz = pn.z();
|
||||
|
||||
float2 fff;
|
||||
|
||||
auto& xf = fff.x();
|
||||
auto& yf = fff.y();
|
||||
//auto& zf = fff.z();
|
||||
|
||||
float* pf = (float*)pn;
|
||||
|
||||
pp.slice<1, 2>() = float2(7.0f, 8.0f);
|
||||
|
||||
Matrix<float, 4, 4> vvvv(
|
||||
Vector<float, 4>(1.0f, 0.0f, 0.0f, 0.0f),
|
||||
Vector<float, 4>(0.0f, 1.0f, 0.0f, 0.0f),
|
||||
Vector<float, 4>(0.0f, 0.0f, 1.0f, 0.0f),
|
||||
Vector<float, 4>(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
auto deg1 = lm::degrees(lm::pi_d);
|
||||
auto deg2 = lm::degrees(lm::pi_d / 2.0);
|
||||
auto deg3 = lm::degrees(double2(pi_d / 2.0, pi_d / 3.0));
|
||||
|
||||
float expf = lm::exp(1.0f);
|
||||
auto expv = lm::exp(float2(2.0f, 3.0f));
|
||||
|
||||
float logf = lm::log(1.0f);
|
||||
auto logv = lm::log(float2(2.0f, 3.0f));
|
||||
|
||||
float minf1 = lm::min(1.0f, 2.0f);
|
||||
float minf2 = lm::min(2.0f, 1.0f);
|
||||
float maxf1 = lm::max(1.0f, 2.0f);
|
||||
float maxf2 = lm::max(2.0f, 1.0f);
|
||||
|
||||
auto clampt = lm::clamp(float2(1.0f, 2.0f), float2(1.5f), float2(3.0f));
|
||||
|
||||
auto minv1 = lm::min(float2(1.0f, 2.0f), float2(5.0f, 1.0f));
|
||||
auto minv2 = lm::min(float2(2.0f, 1.0f), float2(1.0f, 0.0f));
|
||||
auto maxv1 = lm::max(float2(1.0f, 2.0f), float2(0.0f, 0.0f));
|
||||
auto maxv2 = lm::max(float2(2.0f, 1.0f), float2(3.0f, 7.0f));
|
||||
|
||||
auto ux = float3::unitX();
|
||||
auto pow_11 = lm::pow(float4(1.0f, 2.0f, 3.0f, 4.0f), 2.0f);
|
||||
|
||||
Vector<Vector<float, 2>, 2> vv;
|
||||
vv[0] = float2(1.0f, 2.0f);
|
||||
vv[1] = float2(3.0f, 4.0f);
|
||||
auto pow_22 = lm::pow(vv, 2.0f);
|
||||
|
||||
|
||||
test_float2();
|
||||
|
||||
|
||||
|
||||
float3 mul_self_0(1.0f, 2.0f, 3.0f);
|
||||
mul_self_0 *= 2;
|
||||
mul_self_0 *= float3(2.0f, 3.0f, 4.0f);
|
||||
mul_self_0 /= 2;
|
||||
mul_self_0 /= float3(4.0f, 4.0f, 4.0f);
|
||||
mul_self_0 += 1;
|
||||
mul_self_0 += float3(4.0f, 4.0f, 4.0f);
|
||||
|
||||
mul_self_0 -= 2;
|
||||
mul_self_0 -= float3(2.0f, 2.0f, 2.0f);
|
||||
|
||||
//AMP test
|
||||
parallel_for_each(arr.extent, [=](index<1> idx) restrict(amp) {
|
||||
|
||||
|
||||
// Half h1;
|
||||
|
||||
float3x3 m1;
|
||||
|
||||
auto col1 = m1.getColumn(0);
|
||||
auto m2 = float3x3::identity();
|
||||
auto m3 = float4x4::identity();
|
||||
|
||||
auto b2 = float3x3::identity();
|
||||
auto m4 = lm::mul(m1, m2);
|
||||
|
||||
float2x2 m22;
|
||||
|
||||
|
||||
auto det1 = determinant(m22);
|
||||
auto det2 = determinantAffine(m1);
|
||||
auto det3 = determinantAffine(m3);
|
||||
|
||||
auto mi = inverse(m3, true);
|
||||
|
||||
mi[0] = float4{ 0.0f,1.0f,2.0f,3.0f };
|
||||
mi[1] = float4{ 4.0f,5.0f,6.0f,7.0f };
|
||||
mi[2] = float4{ 8.0f,9.0f,10.0f,11.0f };
|
||||
mi[3] = float4{ 12.0f,13.0f,14.0f,15.0f };
|
||||
|
||||
auto mm1 = (float2x2)mi;
|
||||
auto mm2 = (float3x3)mi;
|
||||
auto mm3 = (double4x4)mi;
|
||||
|
||||
|
||||
float3 t3(1.0f);
|
||||
auto len_1 = t3.lengthSquared();
|
||||
auto len_2 = t3.length();
|
||||
|
||||
auto norm_1 = t3.normalized();
|
||||
auto dot_1 = dot(t3, t3);
|
||||
auto cross_1 = cross(float3::unitY(), float3::unitX());
|
||||
|
||||
auto pow_1 = lm::pow(float4(1.0f, 2.0f, 3.0f, 4.0f), 2.0f);
|
||||
auto abs_1 = lm::abs(float4(1.0f, -2.0f, 3.0f, -4.0f));
|
||||
auto acos_1 = lm::acos(float4(1.0f, 0.0f, -1.0f, -0.75f));
|
||||
|
||||
auto asin_1 = lm::asin(float4(1.0f, 0.0f, -1.0f, -0.75f));
|
||||
auto atan_1 = lm::atan(float4(1.0f, 0.0f, -1.0f, -0.75f));
|
||||
|
||||
auto all_1 = lm::all(float4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
auto all_2 = lm::all(float4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
auto all_3 = lm::all(float4(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
auto all_4 = lm::all(float4(0.0f, 1.0f, 1.0f, 1.0f));
|
||||
auto all_5 = lm::all(float4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
auto any_1 = lm::any(float4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
auto any_2 = lm::any(float4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
auto any_3 = lm::any(float4(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
auto any_4 = lm::any(float4(0.0f, 1.0f, 1.0f, 1.0f));
|
||||
auto any_5 = lm::any(float4(1.0f, 1.0f, 1.0f, 1.0f));*/
|
||||
|
||||
/* arr_result[idx] = lm::normalize(t3) + 2;
|
||||
|
||||
float4x4 mat;
|
||||
mat.rows[0] = float4(1, 0, 0, 1);
|
||||
mat.rows[3] = float4(3);
|
||||
auto col0 = mat.get_column(0);
|
||||
|
||||
auto floor_1 = lm::floor(float4(3.3f, 4.4f, 5.5f, 6.6f));
|
||||
auto mat33 = (float3x3)mat;
|
||||
auto mat44 = (float4x4)mat;
|
||||
|
||||
auto mat33_2 = (float3x3)mat;
|
||||
|
||||
auto is_mat1 = lm::matrix_traits::is_matrix<float4x4>::value;
|
||||
auto is_mat2 = lm::matrix_traits::is_matrix<float4>::value;
|
||||
|
||||
auto mmul1 = lm::matrix_traits::can_multiply<float3x3, float3x3>::value;
|
||||
auto mmul2 = lm::matrix_traits::can_multiply<float3x3, float3x4>::value;
|
||||
auto mmul3 = lm::matrix_traits::can_multiply<float3x3, float4x3>::value;
|
||||
|
||||
auto mul_r1 = lm::mul(mat33, mat33_2);
|
||||
|
||||
auto is_identity_constexpr_4x4 = noexcept(float4x4::identity());
|
||||
auto is_identity_constexpr_3x3 = noexcept(float3x3::identity());
|
||||
auto id0 = float4x4::identity();
|
||||
auto id1 = float3x3::identity();
|
||||
auto id2 = float2x2::identity();
|
||||
|
||||
typedef Matrix<double, 5, 5> double5x5;
|
||||
auto is_identity_constexpr_5x5 = noexcept(double5x5::identity());
|
||||
auto id3 = double5x5::identity();
|
||||
|
||||
auto rc = double5x5::rows_count;
|
||||
|
||||
auto mul_r = lm::mul(float3x4(1), float4x3(1));
|
||||
|
||||
auto mul_r2 = lm::mul(float3x3::identity(), float3x3::identity());
|
||||
|
||||
auto mul_r3 = lm::mul(
|
||||
float2x3(float3(1, 3, 2), float3(0, 4, -1)),
|
||||
float3x4(float4(2, 0, -1, 1), float4(3, -2, 1, 2), float4(0, 1, 2, 3)));
|
||||
|
||||
|
||||
auto clamp_1 = lm::clamp(test_vector, 1.0f, 2.0f);
|
||||
auto clamp_2 = lm::clamp(test_matrix, 0.0f, 7.0f);
|
||||
|
||||
|
||||
auto cosh_1 = lm::cosh(test_vector);
|
||||
auto cosh_2 = lm::cosh(test_matrix);
|
||||
|
||||
auto cross_2 = lm::cross(float3(0, 1, 0), float3(0, 0, 1));
|
||||
auto cross_3 = lm::cross(float3(0, 0, 1), float3(0, 1, 0));
|
||||
|
||||
auto degrees_0 = lm::degrees(float3((float)LM_PI / 2.0f, (float)LM_PI / 1.0f, (float)LM_PI / 4.0f));
|
||||
|
||||
auto det_1 = lm::determinant(float2x2(float2(1, 2), float2(-1, 3)));
|
||||
|
||||
auto det_2 = lm::determinant(float3x3::identity());
|
||||
|
||||
|
||||
|
||||
auto norm_2 = lm::normalize(float3(1, 2, 4));
|
||||
|
||||
|
||||
|
||||
});*/
|
||||
|
||||
/*arr_result.synchronize(access_type_auto);
|
||||
|
||||
auto val = std::is_same<float, typename float3::element_type>::value;
|
||||
|
||||
static_assert(sizeof(float2) == sizeof(float) * 2, "Float2 size incorrect");
|
||||
static_assert(sizeof(double2) == sizeof(double) * 2, "double2 size incorrect");
|
||||
|
||||
static_assert(sizeof(float3) == sizeof(float) * 3, "Float2 size incorrect");
|
||||
static_assert(sizeof(double3) == sizeof(double) * 3, "double3 size incorrect");
|
||||
|
||||
static_assert(sizeof(float4) == sizeof(float) * 4, "Float4 size incorrect");
|
||||
static_assert(sizeof(double4) == sizeof(double) * 4, "double4 size incorrect");
|
||||
|
||||
//CPU test
|
||||
test_float2();
|
||||
test_float3();
|
||||
test_float4();
|
||||
|
||||
auto asdouble_0 = lm::asdouble(123, 456);
|
||||
auto asdouble_1 = lm::asdouble(Vector<uint32_t, 2>(2, 2), Vector<uint32_t, 2>(300, 400));
|
||||
|
||||
|
||||
float3x3 m1;
|
||||
auto col1 = m1.get_column(0);
|
||||
auto m2 = float3x3::identity();
|
||||
auto m3 = float4x4::identity();
|
||||
auto m4 = lm::mul(m1, m2);
|
||||
auto det1 = lm::determinant(m4);
|
||||
|
||||
float3 t3(1);
|
||||
auto len_1 = lm::lengthSquared(t3);
|
||||
auto len_2 = lm::length(t3);
|
||||
auto norm_1 = lm::normalize(t3);
|
||||
auto dist_1 = lm::distance(t3, norm_1);
|
||||
auto dot_1 = lm::dot(lm::normalize(t3), lm::normalize(t3));
|
||||
|
||||
|
||||
|
||||
|
||||
std::cin.get();
|
||||
|
||||
|
||||
//static_assert(noexcept(Test_amp()), "Not constexpr (");
|
||||
|
||||
static constexpr float3 f3 = float3::up();
|
||||
|
||||
static constexpr float4 f4 = float4(1, 0, 0, 1);
|
||||
|
||||
static constexpr float4 f4_value = float4(1);
|
||||
|
||||
static constexpr float4 f4_init = { 1.0f,2.0f,3.0f,4.0f };
|
||||
|
||||
|
||||
|
||||
double3 d_add(4);
|
||||
float3 f_add(1);
|
||||
f_add = f_add + 2;
|
||||
|
||||
auto b0 = f_add + d_add;
|
||||
auto b1 = f_add - d_add;
|
||||
auto b2 = f_add * d_add;
|
||||
auto b3 = f_add / d_add;
|
||||
|
||||
auto b4 = f_add + 2;
|
||||
auto b5 = f_add - 2;
|
||||
auto b6 = f_add * 2;
|
||||
auto b7 = f_add / 2;
|
||||
|
||||
float3 fup = float3::up() * 2;
|
||||
double3 dup = double3::up() * 2;
|
||||
|
||||
auto flen_s = lm::lengthSquared(fup);
|
||||
auto flen = lm::length(fup);
|
||||
|
||||
|
||||
auto dlen_s = lm::lengthSquared(dup);
|
||||
auto dlen = lm::length(dup);
|
||||
|
||||
auto pow_1 = lm::pow(float4(1, 2, 3, 4), 2.0f);
|
||||
auto abs_1 = lm::abs(float4(1, -2, 3, -4));
|
||||
auto acos_1 = lm::acos(float4(1, 0, -1, -0.75f));
|
||||
|
||||
float4x4 mat;
|
||||
mat.rows[0] = float4(1, 0, 0, 1);
|
||||
mat.rows[3] = float4(3);
|
||||
auto col0 = mat.get_column(0);
|
||||
|
||||
|
||||
float4x4 mWorld;
|
||||
|
||||
mWorld = float4x4::identity();
|
||||
|
||||
|
||||
auto mat33 = (float3x3)mat;
|
||||
auto mat44 = (float4x4)mat;
|
||||
|
||||
auto mat33_2 = (float3x3)mat;
|
||||
|
||||
auto is_mat1 = lm::matrix_traits::is_matrix<float4x4>::value;
|
||||
auto is_mat2 = lm::matrix_traits::is_matrix<float4>::value;
|
||||
|
||||
auto mmul1 = lm::matrix_traits::can_multiply<float3x3, float3x3>::value;
|
||||
auto mmul2 = lm::matrix_traits::can_multiply<float3x3, float3x4>::value;
|
||||
auto mmul3 = lm::matrix_traits::can_multiply<float3x3, float4x3>::value;
|
||||
|
||||
auto mul_r1 = lm::mul(mat33, mat33_2);
|
||||
|
||||
|
||||
auto is_identity_constexpr_4x4 = noexcept(float4x4::identity());
|
||||
auto is_identity_constexpr_3x3 = noexcept(float3x3::identity());
|
||||
auto id0 = float4x4::identity();
|
||||
auto id1 = float3x3::identity();
|
||||
auto id2 = float2x2::identity();
|
||||
|
||||
|
||||
typedef Matrix<double, 5, 5> double5x5;
|
||||
auto is_identity_constexpr_5x5 = noexcept(double5x5::identity());
|
||||
auto id3 = double5x5::identity();
|
||||
|
||||
auto rc = double5x5::rows_count;
|
||||
|
||||
auto mul_r = lm::mul(float3x4(1), float4x3(1));
|
||||
|
||||
auto mul_r2 = lm::mul(float3x3::identity(), float3x3::identity());
|
||||
|
||||
auto mul_r3 = lm::mul(
|
||||
float2x3(float3(1, 3, 2), float3(0, 4, -1)),
|
||||
float3x4(float4(2, 0, -1, 1), float4(3, -2, 1, 2), float4(0, 1, 2, 3)));
|
||||
|
||||
auto is_square1 = lm::matrix_traits::is_square<double5x5>::value;
|
||||
|
||||
|
||||
|
||||
|
||||
auto asin_1 = lm::asin(float4(1, 0, -1, -0.75f));
|
||||
auto atan_1 = lm::atan(float4(1, 0, -1, -0.75f));
|
||||
|
||||
auto all_1 = lm::all(float4(0, 0, 0, 0));
|
||||
auto all_2 = lm::all(float4(0, 0, 0, 1));
|
||||
auto all_3 = lm::all(float4(0, 0, 1, 1));
|
||||
auto all_4 = lm::all(float4(0, 1, 1, 1));
|
||||
auto all_5 = lm::all(float4(1, 1, 1, 1));
|
||||
|
||||
auto any_1 = lm::any(float4(0, 0, 0, 0));
|
||||
auto any_2 = lm::any(float4(0, 0, 0, 1));
|
||||
auto any_3 = lm::any(float4(0, 0, 1, 1));
|
||||
auto any_4 = lm::any(float4(0, 1, 1, 1));
|
||||
auto any_5 = lm::any(float4(1, 1, 1, 1));
|
||||
|
||||
|
||||
|
||||
|
||||
float4 test_vector = float4(3.3f, 4.4f, 5.5f, 6.6f);
|
||||
float3x3 test_matrix = float3x3(float3(1.1f, 2.2f, 3.3f), float3(4.4f, 5.5f, 6.6f), float3(7.7f, 8.8f, 9.9f));
|
||||
|
||||
auto ceil_1 = lm::ceil(test_vector);
|
||||
auto ceil_2 = lm::ceil(test_matrix);
|
||||
|
||||
auto clamp_1 = lm::clamp(test_vector, 1.0f, 2.0f);
|
||||
auto clamp_2 = lm::clamp(test_matrix, 0.0f, 7.0f);
|
||||
|
||||
auto cos_1 = lm::cos(test_vector);
|
||||
auto cos_2 = lm::cos(test_matrix);
|
||||
|
||||
auto cosh_1 = lm::cosh(test_vector);
|
||||
auto cosh_2 = lm::cosh(test_matrix);
|
||||
|
||||
auto cross_1 = lm::cross(float3(0, 0, 1), float3(1, 0, 0));
|
||||
auto cross_2 = lm::cross(float3(0, 1, 0), float3(0, 0, 1));
|
||||
auto cross_3 = lm::cross(float3(0, 0, 1), float3(0, 1, 0));
|
||||
|
||||
auto degrees_0 = lm::degrees(float3((float)LM_PI / 2.0f, (float)LM_PI / 1.0f, (float)LM_PI / 4.0f));
|
||||
|
||||
auto det_1 = lm::determinant(float2x2(float2(1, 2), float2(-1, 3)));
|
||||
|
||||
auto det_2 = lm::determinant(float3x3::identity());
|
||||
|
||||
|
||||
|
||||
auto norm_2 = lm::normalize(float3(1, 2, 4));
|
||||
|
||||
auto p1 = float3::up() / lm::length(float3::up());
|
||||
|
||||
|
||||
|
||||
|
||||
auto dot_2 = lm::dot(float3::up(), float3::up());
|
||||
auto dot_3 = lm::dot(float3::up(), lm::normalize(float3::up() + float3::right()));
|
||||
|
||||
auto deg_1 = lm::degrees(std::acos(dot_1));
|
||||
auto deg_2 = lm::degrees(std::acos(dot_2));
|
||||
auto deg_3 = lm::degrees(std::acos(dot_3));
|
||||
|
||||
|
||||
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{9CB05983-8BE8-44E9-9E0D-63EBC7F37592}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>lmath_sandbox</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LM_AMP_SUPPORTED</PreprocessorDefinitions>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<CppLanguageStandard>gnu++1y</CppLanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);LM_AMP_SUPPORTED</PreprocessorDefinitions>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<CppLanguageStandard>gnu++1y</CppLanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LM_AMP_SUPPORTED</PreprocessorDefinitions>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<CppLanguageStandard>gnu++1y</CppLanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LM_AMP_SUPPORTED</PreprocessorDefinitions>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<CppLanguageStandard>gnu++1y</CppLanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="lmath_sandbox.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
#include "stdafx.h"
|
||||
#include "CppUnitTest.h"
|
||||
#include "../Src/lmath/lmath.h"
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace lm;
|
||||
|
||||
namespace lmath_test {
|
||||
TEST_CLASS(lm_half_test_class) {
|
||||
public:
|
||||
TEST_METHOD(lm_half_test) {
|
||||
const float tolerance = 0.01f;
|
||||
Half h1;
|
||||
|
||||
h1 = 1.0f;
|
||||
Assert::AreEqual(1.0f, h1.toFloat(), tolerance);
|
||||
h1 = 0.0f;
|
||||
Assert::AreEqual(0.0f, h1.toFloat(), tolerance);
|
||||
h1 = -1.0f;
|
||||
Assert::AreEqual(-1.0f, h1.toFloat(), tolerance);
|
||||
h1 = -2.34f;
|
||||
Assert::AreEqual(-2.34f, h1.toFloat(), tolerance);
|
||||
|
||||
|
||||
Assert::IsFalse(h1.isNan());
|
||||
Assert::IsFalse(std::isnan(h1.toFloat()));
|
||||
Assert::IsFalse(h1.isInf());
|
||||
Assert::IsFalse(std::isinf(h1.toFloat()));
|
||||
|
||||
h1 = std::numeric_limits<float>::signaling_NaN();
|
||||
Assert::IsTrue(h1.isNan());
|
||||
Assert::IsTrue(std::isnan(h1.toFloat()));
|
||||
|
||||
h1 = std::numeric_limits<float>::infinity();
|
||||
Assert::IsTrue(h1.isInf());
|
||||
Assert::IsTrue(std::isinf(h1.toFloat()));
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "stdafx.h"
|
||||
#include "CppUnitTest.h"
|
||||
#include "../Src/lmath/lmath.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace lm;
|
||||
|
||||
namespace lmath_test {
|
||||
TEST_CLASS(lm_matrix_test_class) {
|
||||
public:
|
||||
TEST_METHOD(lm_matrix_test) {
|
||||
lm::float3 z = lm::float3::unitZ();
|
||||
auto ryp90 = lm::matrix4x4RotationY<float>(lm::pi_f / 2.0f);
|
||||
auto ryn90 = lm::matrix4x4RotationY<float>(-lm::pi_f / 2.0f);
|
||||
auto xp = lm::mul(ryp90, lm::float4(z, 1.0f)).slice<0,3>();
|
||||
auto xn = lm::mul(ryn90, lm::float4(z, 1.0f)).slice<0, 3>();
|
||||
|
||||
Assert::IsTrue(xp.equals(lm::float3::unitX(), 0.001f));
|
||||
Assert::IsTrue(xn.equals(lm::float3::unitX() * -1.0f, 0.001f));
|
||||
}
|
||||
|
||||
TEST_METHOD(lm_matrix_rotation_quaternion) {
|
||||
auto m0 = lm::matrix4x4RotationY<float>(lm::pi_f / 2.0f);
|
||||
auto m1 = matrix4x4RotationQuaternion(lm::Quaternion_f::angleAxis(lm::pi_f / 2.0f, float3::unitY()));
|
||||
|
||||
for (LmSize y = 0; y < 4; ++y) {
|
||||
for (LmSize x = 0; x < 4; ++x) {
|
||||
Assert::AreEqual(m0[y][x], m1[y][x], 0.0001f);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "stdafx.h"
|
||||
#include "CppUnitTest.h"
|
||||
#include "../Src/lmath/lmath.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace lm;
|
||||
|
||||
namespace lmath_test {
|
||||
TEST_CLASS(lm_quaternion_test_class) {
|
||||
public:
|
||||
TEST_METHOD(lm_quaternion_test) {
|
||||
lm::Quaternion<float> q(0.0f, 1.0f, 2.0f, 3.0f);
|
||||
Assert::AreEqual(0.0f, q[0]);
|
||||
Assert::AreEqual(1.0f, q[1]);
|
||||
Assert::AreEqual(2.0f, q[2]);
|
||||
Assert::AreEqual(3.0f, q[3]);
|
||||
|
||||
q = Quaternion<float>::identity();
|
||||
Assert::AreEqual(0.0f, q[0]);
|
||||
Assert::AreEqual(0.0f, q[1]);
|
||||
Assert::AreEqual(0.0f, q[2]);
|
||||
Assert::AreEqual(1.0f, q[3]);
|
||||
|
||||
|
||||
lm::Quaternion<float> q2 = q;
|
||||
|
||||
auto q1 = lm::Quaternion_f::angleAxis(lm::pi_f / 2.0f, float3::unitY());
|
||||
|
||||
Assert::AreEqual(0.0f, q1[0], L"Q0");
|
||||
Assert::AreEqual(lm::cos(lm::pi_f / 4.0f), q1[1], L"Q1");
|
||||
Assert::AreEqual(0.0f, q1[2], L"Q2");
|
||||
Assert::AreEqual(lm::cos(lm::pi_f / 4.0f), q1[3], L"Q3");
|
||||
|
||||
q1 = q1 * q1;
|
||||
|
||||
auto q3 = lm::Quaternion_f::angleAxis(lm::pi_f, float3::unitY());
|
||||
|
||||
const float epsilon = 0.0001f;
|
||||
Assert::AreEqual(q3[0], q1[0], epsilon, L"Q0");
|
||||
Assert::AreEqual(q3[1], q1[1], epsilon, L"Q1");
|
||||
Assert::AreEqual(q3[2], q1[2], epsilon, L"Q2");
|
||||
Assert::AreEqual(q3[3], q1[3], epsilon, L"Q3");
|
||||
|
||||
Assert::AreEqual(0.0f, q1[0], epsilon, L"Q0");
|
||||
Assert::AreEqual(1.0f, q1[1], epsilon, L"Q1");
|
||||
Assert::AreEqual(0.0f, q1[2], epsilon, L"Q2");
|
||||
Assert::AreEqual(0.0f, q1[3], epsilon, L"Q3");
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "stdafx.h"
|
||||
#include "CppUnitTest.h"
|
||||
#include "../Src/lmath/lmath.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace lm;
|
||||
|
||||
namespace lmath_test{
|
||||
TEST_CLASS(lm_traits_test_class){
|
||||
public:
|
||||
TEST_METHOD(lm_traits_test){
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
+424
@@ -0,0 +1,424 @@
|
||||
#include "stdafx.h"
|
||||
#include "CppUnitTest.h"
|
||||
#include "../Src/lmath/lmath.h"
|
||||
#include "../Src/lmath/lm_vector_sse.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace lm;
|
||||
|
||||
namespace lmath_test {
|
||||
TEST_CLASS(lm_vector_test_class) {
|
||||
public:
|
||||
|
||||
TEST_METHOD(lm_vector_test_sse_constructors_and_getters) {
|
||||
lm::float4_sse v0;
|
||||
Assert::AreEqual(0.0f, v0.get<0>());
|
||||
Assert::AreEqual(0.0f, v0.get<1>());
|
||||
Assert::AreEqual(0.0f, v0.get<2>());
|
||||
Assert::AreEqual(0.0f, v0.get<3>());
|
||||
|
||||
lm::float4_sse v1(5.0f);
|
||||
Assert::AreEqual(5.0f, v1.get<0>(), L"0");
|
||||
Assert::AreEqual(5.0f, v1.get<1>(), L"1");
|
||||
Assert::AreEqual(5.0f, v1.get<2>(), L"2");
|
||||
Assert::AreEqual(5.0f, v1.get<3>(), L"3");
|
||||
|
||||
lm::float4_sse v2(2,3,4,5);
|
||||
Assert::AreEqual(2.0f, v2.get<0>(), L"0");
|
||||
Assert::AreEqual(3.0f, v2.get<1>(), L"1");
|
||||
Assert::AreEqual(4.0f, v2.get<2>(), L"2");
|
||||
Assert::AreEqual(5.0f, v2.get<3>(), L"3");
|
||||
|
||||
Assert::AreEqual(v2.get(0), v2.get<0>(), L"0");
|
||||
Assert::AreEqual(v2.get(1), v2.get<1>(), L"1");
|
||||
Assert::AreEqual(v2.get(2), v2.get<2>(), L"2");
|
||||
Assert::AreEqual(v2.get(3), v2.get<3>(), L"3");
|
||||
|
||||
|
||||
auto m1 = v2 * v2;
|
||||
Assert::AreEqual(m1.get<0>(), 4.0f, L"0");
|
||||
Assert::AreEqual(m1.get<1>(), 9.0f, L"1");
|
||||
Assert::AreEqual(m1.get<2>(), 16.0f, L"2");
|
||||
Assert::AreEqual(m1.get<3>(), 25.0f, L"3");
|
||||
|
||||
v2 *= v2;
|
||||
Assert::AreEqual(v2.get<0>(), 4.0f, L"0");
|
||||
Assert::AreEqual(v2.get<1>(), 9.0f, L"1");
|
||||
Assert::AreEqual(v2.get<2>(), 16.0f, L"2");
|
||||
Assert::AreEqual(v2.get<3>(), 25.0f, L"3");
|
||||
|
||||
auto d1 = lm::float4_sse{ 2,4,6,8 };
|
||||
auto d2 = d1 / lm::float4_sse{ 2,2,3,4 };
|
||||
|
||||
Assert::AreEqual(d2.get<0>(), 1.0f, L"0");
|
||||
Assert::AreEqual(d2.get<1>(), 2.0f, L"1");
|
||||
Assert::AreEqual(d2.get<2>(), 2.0f, L"2");
|
||||
Assert::AreEqual(d2.get<3>(), 2.0f, L"3");
|
||||
|
||||
d1 /= lm::float4_sse{ 2,2,3,4 };
|
||||
Assert::AreEqual(d1.get<0>(), 1.0f, L"0");
|
||||
Assert::AreEqual(d1.get<1>(), 2.0f, L"1");
|
||||
Assert::AreEqual(d1.get<2>(), 2.0f, L"2");
|
||||
Assert::AreEqual(d1.get<3>(), 2.0f, L"3");
|
||||
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
void testMin() {
|
||||
Assert::IsTrue(lm::min(1.0f, 2.0f) == 1.0f);
|
||||
Assert::IsTrue(lm::min(2.0f, 1.0f) == 1.0f);
|
||||
|
||||
V v1(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
V v2(-5.0f, 0.0f, 5.0f, 7.0f);
|
||||
|
||||
const float epsilon = 0.001f;
|
||||
Assert::IsTrue(lm::min(v1, v2).equals(V(-5.0f, 0.0f, 3.0f, 4.0f), epsilon));
|
||||
Assert::IsTrue(lm::min(v2, v1).equals(V(-5.0f, 0.0f, 3.0f, 4.0f), epsilon));
|
||||
Assert::IsTrue(lm::max(v1, v2).equals(V(1.0f, 2.0f, 5.0f, 7.0f), epsilon));
|
||||
Assert::IsTrue(lm::max(v2, v1).equals(V(1.0f, 2.0f, 5.0f, 7.0f), epsilon));
|
||||
|
||||
Assert::AreEqual(1.0f, lm::min(v1), epsilon);
|
||||
Assert::AreEqual(-5.0f, lm::min(v2), epsilon);
|
||||
|
||||
Assert::AreEqual(4.0f, lm::max(v1), epsilon);
|
||||
Assert::AreEqual(7.0f, lm::max(v2), epsilon);
|
||||
}
|
||||
|
||||
TEST_METHOD(lm_vector_test_min_sse) {
|
||||
testMin<float4_sse>();
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_dot_sse) {
|
||||
Assert::AreEqual(0.0f, dot(float4_sse(), float4_sse()));
|
||||
Assert::AreEqual(1.0f, dot(float4_sse(1,1,1,1), float4_sse(1,0,0,0)));
|
||||
}
|
||||
|
||||
TEST_METHOD(lm_vector_test_min) {
|
||||
testMin<float4>();
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_operators) {
|
||||
float3 v1(0.0f);
|
||||
float3 v2(2.0f);
|
||||
double3 v3(0.0);
|
||||
|
||||
Assert::IsTrue(v1 == v1);
|
||||
Assert::IsFalse(v1 != v1);
|
||||
|
||||
Assert::IsFalse(v1 == v2);
|
||||
Assert::IsTrue(v1 != v2);
|
||||
|
||||
Assert::IsTrue(v1 == v3);
|
||||
Assert::IsFalse(v1 != v3);
|
||||
const float epsilon = 0.0001f;
|
||||
|
||||
v2 = v2 / 2.0f;
|
||||
Assert::IsTrue(v2.equals(float3(1.0f), epsilon));
|
||||
v2 = v2 * 5.0f;
|
||||
Assert::IsTrue(v2.equals(float3(5.0f), epsilon));
|
||||
v2 = v2 + 5.0f;
|
||||
Assert::IsTrue(v2.equals(float3(10.0f), epsilon));
|
||||
v2 = v2 - 9.0f;
|
||||
Assert::IsTrue(v2.equals(float3(1.0f), epsilon));
|
||||
v2 *= 3.0f;
|
||||
Assert::IsTrue(v2.equals(float3(3.0f), epsilon));
|
||||
v2 /= 6.0f;
|
||||
Assert::IsTrue(v2.equals(float3(0.5f), epsilon));
|
||||
v2 += 1.5f;
|
||||
Assert::IsTrue(v2.equals(float3(2.0f), epsilon));
|
||||
v2 -= 2.0f;
|
||||
Assert::IsTrue(v2.equals(float3(0.0f), epsilon));
|
||||
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_constructors_N1) {
|
||||
Vector<float, 1> v1{};
|
||||
Vector<float, 1> v2(2.2f);
|
||||
Vector<float, 1> v3{ 3.3f };
|
||||
Vector<float, 1> v4 = v3;
|
||||
|
||||
Vector<float, 1> v5;
|
||||
v5 = v3;
|
||||
|
||||
Assert::AreEqual(2.2f, v2[0], L"v2 ctor fail");
|
||||
Assert::AreEqual(3.3f, v3[0], L"v3 ctor fail");
|
||||
Assert::AreEqual(3.3f, v4[0], L"v4 ctor fail");
|
||||
Assert::AreEqual(3.3f, v5[0], L"v5 ctor fail");
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_constructors_N2) {
|
||||
Vector<float, 2> v1{};
|
||||
Vector<float, 2> v2(2.2f, 3.3f);
|
||||
Vector<float, 2> v3{ 4.4f };
|
||||
Assert::AreEqual(2.2f, v2[0], L"v2 ctor fail");
|
||||
Assert::AreEqual(3.3f, v2[1], L"v2 ctor fail");
|
||||
Assert::AreEqual(4.4f, v3[0], L"v3 ctor fail");
|
||||
Assert::AreEqual(4.4f, v3[1], L"v3 ctor fail");
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_constructors_N3) {
|
||||
Vector<float, 3> v1{};
|
||||
Vector<float, 3> v2(2.2f, 3.3f, 4.4f);
|
||||
Vector<float, 3> v3{ 5.5f };
|
||||
|
||||
Assert::AreEqual(2.2f, v2[0], L"v2 ctor fail");
|
||||
Assert::AreEqual(3.3f, v2[1], L"v2 ctor fail");
|
||||
Assert::AreEqual(4.4f, v2[2], L"v2 ctor fail");
|
||||
|
||||
Assert::AreEqual(5.5f, v3[0], L"v3 ctor fail");
|
||||
Assert::AreEqual(5.5f, v3[1], L"v3 ctor fail");
|
||||
Assert::AreEqual(5.5f, v3[2], L"v3 ctor fail");
|
||||
|
||||
Vector<float, 2> v4(1.1f, 2.2f);
|
||||
Vector<float, 3> v5(v4, 3.3f);
|
||||
|
||||
Assert::AreEqual(1.1f, v5[0], L"v5 ctor fail");
|
||||
Assert::AreEqual(2.2f, v5[1], L"v5 ctor fail");
|
||||
Assert::AreEqual(3.3f, v5[2], L"v5 ctor fail");
|
||||
|
||||
Vector<float, 3> v6(3.3f, v4);
|
||||
|
||||
Assert::AreEqual(3.3f, v6[0], L"v6 ctor fail");
|
||||
Assert::AreEqual(1.1f, v6[1], L"v6 ctor fail");
|
||||
Assert::AreEqual(2.2f, v6[2], L"v6 ctor fail");
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_constructors_N4) {
|
||||
Vector<float, 4> v1{};
|
||||
Vector<float, 4> v2(1.1f, 2.2f, 3.3f, 4.4f);
|
||||
Vector<float, 4> v3{ 5.5f };
|
||||
|
||||
Assert::AreEqual(1.1f, v2[0], L"v2 ctor fail");
|
||||
Assert::AreEqual(2.2f, v2[1], L"v2 ctor fail");
|
||||
Assert::AreEqual(3.3f, v2[2], L"v2 ctor fail");
|
||||
Assert::AreEqual(4.4f, v2[3], L"v2 ctor fail");
|
||||
|
||||
Assert::AreEqual(5.5f, v3[0], L"v3 ctor fail");
|
||||
Assert::AreEqual(5.5f, v3[1], L"v3 ctor fail");
|
||||
Assert::AreEqual(5.5f, v3[2], L"v3 ctor fail");
|
||||
Assert::AreEqual(5.5f, v3[3], L"v3 ctor fail");
|
||||
|
||||
Vector<float, 2> p2_1{ 6.6f, 7.7f };
|
||||
Vector<float, 2> p2_2{ 8.8f, 9.9f };
|
||||
Vector<float, 3> p3{ 6.0f, 7.0f, 8.0f };
|
||||
|
||||
Vector<float, 4> v4{ p2_1, p2_2 };
|
||||
Assert::AreEqual(p2_1[0], v4[0], L"v4 ctor fail");
|
||||
Assert::AreEqual(p2_1[1], v4[1], L"v4 ctor fail");
|
||||
Assert::AreEqual(p2_2[0], v4[2], L"v4 ctor fail");
|
||||
Assert::AreEqual(p2_2[1], v4[3], L"v4 ctor fail");
|
||||
|
||||
Vector<float, 4> v5(p2_1, 2.0f, 3.0f);
|
||||
Assert::AreEqual(p2_1[0], v5[0], L"v5 ctor fail");
|
||||
Assert::AreEqual(p2_1[1], v5[1], L"v5 ctor fail");
|
||||
Assert::AreEqual(2.0f, v5[2], L"v5 ctor fail");
|
||||
Assert::AreEqual(3.0f, v5[3], L"v5 ctor fail");
|
||||
|
||||
Vector<float, 4> v6(2.0f, 3.0f, p2_1);
|
||||
Assert::AreEqual(2.0f, v6[0], L"v6 ctor fail");
|
||||
Assert::AreEqual(3.0f, v6[1], L"v6 ctor fail");
|
||||
Assert::AreEqual(p2_1[0], v6[2], L"v6 ctor fail");
|
||||
Assert::AreEqual(p2_1[1], v6[3], L"v6 ctor fail");
|
||||
|
||||
|
||||
Vector<float, 4> v7(p3, 9.9f);
|
||||
Assert::AreEqual(p3[0], v7[0], L"v7 ctor fail");
|
||||
Assert::AreEqual(p3[1], v7[1], L"v7 ctor fail");
|
||||
Assert::AreEqual(p3[2], v7[2], L"v7 ctor fail");
|
||||
Assert::AreEqual(9.9f, v7[3], L"v7 ctor fail");
|
||||
|
||||
Vector<float, 4> v8(9.9f, p3);
|
||||
Assert::AreEqual(9.9f, v8[0], L"v8 ctor fail");
|
||||
Assert::AreEqual(p3[0], v8[1], L"v8 ctor fail");
|
||||
Assert::AreEqual(p3[1], v8[2], L"v8 ctor fail");
|
||||
Assert::AreEqual(p3[2], v8[3], L"v8 ctor fail");
|
||||
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_constructors_N) {
|
||||
Vector<float, 7> v1(5.5f);
|
||||
for (LmSize i = 0; i < 7; ++i) {
|
||||
Assert::AreEqual(5.5f, v1[i], L"Vector N ctor fail");
|
||||
}
|
||||
|
||||
Vector<float, 7> v2(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f);
|
||||
for (LmSize i = 0; i < 7; ++i) {
|
||||
Assert::AreEqual((float)i, v2[i], L"Vector N ctor fail");
|
||||
}
|
||||
|
||||
v1 = v2;
|
||||
|
||||
for (LmSize i = 0; i < 7; ++i) {
|
||||
Assert::AreEqual((float)i, v1[i], L"Vector N ctor fail");
|
||||
}
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_slice) {
|
||||
float3 v1(1.0f, 2.0f, 3.0f);
|
||||
|
||||
auto& s1 = v1.slice<0, 1>();
|
||||
Assert::AreEqual((LmSize)1, s1.Size, L"Invalid slice size");
|
||||
Assert::AreEqual(1.0f, s1[0], L"Invalid slice value");
|
||||
|
||||
auto& s2 = v1.slice<0, 2>();
|
||||
Assert::AreEqual((LmSize)2, s2.Size, L"Invalid slice size");
|
||||
Assert::AreEqual(1.0f, s2[0], L"Invalid slice value");
|
||||
Assert::AreEqual(2.0f, s2[1], L"Invalid slice value");
|
||||
|
||||
auto& s3 = v1.slice<0, 3>();
|
||||
Assert::AreEqual((LmSize)3, s3.Size, L"Invalid slice size");
|
||||
Assert::AreEqual(1.0f, s3[0], L"Invalid slice value");
|
||||
Assert::AreEqual(2.0f, s3[1], L"Invalid slice value");
|
||||
Assert::AreEqual(3.0f, s3[2], L"Invalid slice value");
|
||||
|
||||
auto& s4 = v1.slice<1, 1>();
|
||||
Assert::AreEqual((LmSize)1, s4.Size, L"Invalid slice size");
|
||||
Assert::AreEqual(2.0f, s4[0], L"Invalid slice value");
|
||||
|
||||
auto& s5 = v1.slice<2, 1>();
|
||||
Assert::AreEqual((LmSize)1, s5.Size, L"Invalid slice size");
|
||||
Assert::AreEqual(3.0f, s5[0], L"Invalid slice value");
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_dot) {
|
||||
double3 x{ 1.0, 0.0, 0.0 };
|
||||
double3 y{ 0.0, 1.0, 0.0 };
|
||||
double3 z{ 0.0, 0.0, 1.0 };
|
||||
|
||||
double3 _x{ -1.0, 0.0, 0.0 };
|
||||
|
||||
const double dotTolerance = 0.01;
|
||||
Assert::AreEqual(1.0, lm::dot(x, x), dotTolerance, L"Dot fail");
|
||||
Assert::AreEqual(1.0, lm::dot(y, y), dotTolerance, L"Dot fail");
|
||||
Assert::AreEqual(1.0, lm::dot(z, z), dotTolerance, L"Dot fail");
|
||||
|
||||
Assert::AreEqual(0.0, lm::dot(x, y), dotTolerance, L"Dot fail");
|
||||
Assert::AreEqual(0.0, lm::dot(y, z), dotTolerance, L"Dot fail");
|
||||
Assert::AreEqual(0.0, lm::dot(x, z), dotTolerance, L"Dot fail");
|
||||
|
||||
Assert::AreEqual(-1.0, lm::dot(x, _x), dotTolerance, L"Dot fail");
|
||||
|
||||
double3 w{ 1.0, 1.0, 0.0 };
|
||||
w = lm::normalize(w);
|
||||
|
||||
Assert::AreEqual(std::cos(lm::pi_d / 4.0), lm::dot(y, w), dotTolerance, L"Dot fail");
|
||||
Assert::AreEqual(-std::cos(lm::pi_d / 4.0), lm::dot(y, w * -1.0f), dotTolerance, L"Dot fail");
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_trigonometry) {
|
||||
float3 v{ 2.0f, 3.0f, 4.0f };
|
||||
|
||||
auto vSin = lm::sin(v);
|
||||
|
||||
Assert::AreEqual(std::sin(v[0]), vSin[0], L"Sin fail");
|
||||
Assert::AreEqual(std::sin(v[1]), vSin[1], L"Sin fail");
|
||||
Assert::AreEqual(std::sin(v[2]), vSin[2], L"Sin fail");
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_all_any) {
|
||||
float3 v1{ 0.0f, 0.0f, 0.0f };
|
||||
float3 v2{ 0.0f, 0.0f, 3.0f };
|
||||
float3 v3{ 3.0f, 3.0f, 3.0f };
|
||||
|
||||
Assert::IsFalse(lm::all(v1));
|
||||
Assert::IsFalse(lm::any(v1));
|
||||
|
||||
Assert::IsFalse(lm::all(v2));
|
||||
Assert::IsTrue(lm::any(v2));
|
||||
|
||||
Assert::IsTrue(lm::all(v3));
|
||||
Assert::IsTrue(lm::any(v3));
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_unit) {
|
||||
auto x2 = float2::unitX();
|
||||
auto y2 = float2::unitY();
|
||||
|
||||
Assert::AreEqual(1.0f, x2[0]);
|
||||
Assert::AreEqual(0.0f, x2[1]);
|
||||
|
||||
Assert::AreEqual(0.0f, y2[0]);
|
||||
Assert::AreEqual(1.0f, y2[1]);
|
||||
|
||||
auto z3 = float3::unitZ();
|
||||
auto w4 = float4::unitW();
|
||||
|
||||
Assert::AreEqual(0.0f, z3[0]);
|
||||
Assert::AreEqual(0.0f, z3[1]);
|
||||
Assert::AreEqual(1.0f, z3[2]);
|
||||
|
||||
|
||||
Assert::AreEqual(0.0f, w4[0]);
|
||||
Assert::AreEqual(0.0f, w4[1]);
|
||||
Assert::AreEqual(0.0f, w4[2]);
|
||||
Assert::AreEqual(1.0f, w4[3]);
|
||||
}
|
||||
TEST_METHOD(lm_vector_test_length_lengthSquared) {
|
||||
float3 v1{ 1.0f, 0.0f, 0.0f };
|
||||
float3 v2{ 0.0f, 2.0f, 0.0f };
|
||||
float3 v3{ 1.0f, 1.0f, 0.0f };
|
||||
const float tolerance = 0.001f;
|
||||
|
||||
Assert::AreEqual(1.0f, v1.length(), tolerance);
|
||||
Assert::AreEqual(1.0f, v1.lengthSquared(), tolerance);
|
||||
|
||||
Assert::AreEqual(2.0f, v2.length(), tolerance);
|
||||
Assert::AreEqual(4.0f, v2.lengthSquared(), tolerance);
|
||||
|
||||
Assert::AreEqual(std::sqrt(2.0f), v3.length(), tolerance);
|
||||
Assert::AreEqual(2.0f, v3.lengthSquared(), tolerance);
|
||||
}
|
||||
|
||||
TEST_METHOD(lm_vector_test_equals) {
|
||||
float3 v1(1.0f, 2.0f, 3.0f);
|
||||
float3 v2(2.0f, 2.0f, 3.0f);
|
||||
|
||||
float tolerance = 0.001f;
|
||||
Assert::IsTrue(v1.equals(v1, tolerance));
|
||||
Assert::IsFalse(v1.equals(v2, tolerance));
|
||||
|
||||
for (LmSize i = 0; i < 3; ++i) {
|
||||
v2[i] = v1[i] + tolerance * 2.0f;
|
||||
}
|
||||
|
||||
Assert::IsFalse(v1.equals(v2, tolerance));
|
||||
|
||||
}
|
||||
|
||||
TEST_METHOD(lm_vector_test_cross) {
|
||||
float3 x{ 1.0f, 0.0f, 0.0f };
|
||||
float3 y{ 0.0f, 1.0f, 0.0f };
|
||||
float3 z{ 0.0f, 0.0f, 1.0f };
|
||||
const float tolerance = 0.001f;
|
||||
|
||||
auto c1 = lm::cross(y, z);
|
||||
auto c2 = lm::cross(z, y);
|
||||
|
||||
Assert::AreEqual(1.0f, c1[0], tolerance);
|
||||
Assert::AreEqual(0.0f, c1[1], tolerance);
|
||||
Assert::AreEqual(0.0f, c1[2], tolerance);
|
||||
|
||||
Assert::AreEqual(-1.0f, c2[0], tolerance);
|
||||
Assert::AreEqual(0.0f, c2[1], tolerance);
|
||||
Assert::AreEqual(0.0f, c2[2], tolerance);
|
||||
|
||||
}
|
||||
|
||||
TEST_METHOD(lm_vector_test_normalize) {
|
||||
float3 v1{ 1.0f,0.0f, 0.0f };
|
||||
float3 v2{ 2.0f,0.0f, 0.0f };
|
||||
float3 v3{ 2.0f,2.0f, 2.0f };
|
||||
float3 v4{ -2.0f, -2.0f, -2.0f };
|
||||
|
||||
const float tolerance = 0.001f;
|
||||
Assert::AreEqual(1.0f, v1.normalized().length(), tolerance);
|
||||
Assert::AreEqual(1.0f, v2.normalized().length(), tolerance);
|
||||
Assert::AreEqual(1.0f, v3.normalized().length(), tolerance);
|
||||
Assert::AreEqual(1.0f, v4.normalized().length(), tolerance);
|
||||
}
|
||||
|
||||
TEST_METHOD(lm_vector_test_lerp) {
|
||||
float3 v1{ -1.0f };
|
||||
float3 v2{ 1.0f};
|
||||
|
||||
const float tolerance = 0.001f;
|
||||
Assert::IsTrue(lm::lerp(v1, v2, 0.0f).equals(v1, tolerance));
|
||||
Assert::IsTrue(lm::lerp(v1, v2, 1.0f).equals(v2, tolerance));
|
||||
Assert::IsTrue(lm::lerp(v1, v2, 0.5f).equals(float3(0.0f, 0.0f, 0.0f), tolerance));
|
||||
Assert::IsTrue(lm::lerp(v1, v2, 0.1f).equals(float3(-0.8f, -0.8f, -0.8f), tolerance));
|
||||
Assert::IsTrue(lm::lerp(v1, v2, 0.9f).equals(float3(0.8f, 0.8f, 0.8f), tolerance));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{DD9111B5-C46C-4BA6-973C-362BD5946348}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>lmath_test</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="lm_half_tests.cpp" />
|
||||
<ClCompile Include="lm_matrix_test.cpp" />
|
||||
<ClCompile Include="lm_quaternion_test.cpp" />
|
||||
<ClCompile Include="lm_vector_test.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="lm_traits_test.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// lmath_test.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: reference any additional headers you need in STDAFX.H
|
||||
// and not in this file
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
||||
// Headers for CppUnitTest
|
||||
#include "CppUnitTest.h"
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
||||
Reference in New Issue
Block a user